<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x633;&#x64A;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644;</title><link>https://academy.hsoub.com/programming/workflow/page/2/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x633;&#x64A;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644;</description><language>ar</language><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642; &#x648;&#x64A;&#x628; &#x645;&#x62A;&#x643;&#x627;&#x645;&#x644; &#x648;&#x628;&#x646;&#x627;&#x624;&#x647; &#x639;&#x628;&#x631; Yeoman</title><link>https://academy.hsoub.com/programming/workflow/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%88%D9%8A%D8%A8-%D9%85%D8%AA%D9%83%D8%A7%D9%85%D9%84-%D9%88%D8%A8%D9%86%D8%A7%D8%A4%D9%87-%D8%B9%D8%A8%D8%B1-yeoman-r761/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_11/5dc07b8ac9a4a_---Yeoman----.jpg.596a694438a851b2376da17acda5f023.jpg" /></p>

<p>
	يعدُّ <a href="https://yeoman.io" rel="external nofollow">Yeoman</a> (وتلفظ «يومِن» ومعناها في اللغة الأجنبية الخادم الجليل الذي يخدم النبلاء أو الشخص الذي يقدم خدمات جليلة ذات شأن) نظامًا عامًّا للسقالات يسمح بإنشاء أي نوع من التطبيقات، فهو يتيح البدء السريع في مشاريع جديدة ويبسّط صيانة المشاريع القائمة. <a href="https://ar.wikipedia.org/wiki/%D8%B3%D9%82%D8%A7%D9%84%D8%A9" rel="external nofollow">السقالة</a> باللغة العربية هي هيكل مؤقت يُستخدَم في حمل الأشخاص والمواد بغرض البناء؛ أمَّا في البرمجة، فينطبق التعريف تمامًا عليها أي هي منصةٌ مؤقتةٌ تُستعمَل في بناء هياكل التطبيقات للانطلاق بعملية الإنشاء بسرعة وذلك بتوليد الملفات البدائية الأساسية للمشروع أو التطبيق (الهيكل العام) الذي تود إنشاءه وفق مواصفات ومعايير تحدِّدها مما يوفر عليك الكثير من الوقت.
</p>

<p>
	ويمكن القول أنَّ Yeoman محايدٌ مع لغات البرمجة أي يسمح بإنشاء مشاريع بأي لغة تريد (لغات الويب أو لغة جافا أو بايثون أو سي شارب أو غيرها).
</p>

<p>
	لا يتخذ Yeoman في حد ذاته أي قرارات. تُتخَذ كل القرارات من قبل المولّدات التي هي في الأساس ملحقات في بيئة Yeoman. هناك الكثير من <a href="https://yeoman.io/generators/" rel="external nofollow">المولدات</a> المتاحة كما أنّه من السهل <a href="https://yeoman.io/authoring/" rel="external nofollow">إنشاء مولّد جديد</a> يناسب أي سير عمل تريد. Yeoman هو دائمًا خيارك الصحيح لاحتياجات بناء التطبيقات وتوليد ملفات المشروع الابتدائية.
</p>

<p>
	فيما يلي بعض حالات الاستخدام الشائعة له:
</p>

<ul>
<li>
		إنشاء مشروع جديد بسرعة
	</li>
	<li>
		إنشاء أقسام جديدة من المشروع، مثل وحدة تحكم جديدة مع اختبارات الوحدة
	</li>
	<li>
		إنشاء وحدات (modules) أو حزم (packages)
	</li>
	<li>
		التمهيد لخدمات جديدة
	</li>
	<li>
		فرض المعايير والممارسات الجيّدة والدلائل النمطية
	</li>
	<li>
		الترويج لمشاريع جديدة من خلال السماح للمستخدمين بالبدء مع تطبيق أو مشروع نموذجي
	</li>
	<li>
		وغيرها من حالات الاستخدام
	</li>
</ul>
<h2>
	جدول المحتويات
</h2>

<p>
	حرصًا على تنظيم المقالة ولتسهيل الوصول إلى القسم الذي تريده بسهولة، سنذكر هنا جدول المحتويات باختصار:
</p>

<ul>
<li>
		<a href="#p10" rel="">الجزء الأول: البدء مع Yeoman</a>

		<ul>
<li>
				<a href="#p11" rel="">تثبيت <code>yo</code> وبعض المولدات</a>
			</li>
			<li>
				<a href="#p12" rel="">تنصيب السقالة واستخدامها عمليًا</a>
			</li>
			<li>
				<a href="#p13" rel="">أوامر <code>yo</code> الأخرى</a>
			</li>
			<li>
				<a href="#p14" rel="">استكشاف الأخطاء وإصلاحها</a>
			</li>
		</ul>
</li>
	<li>
		<a href="#p20" rel="">الجزء الثاني: تنصيب سقالة Yeoman لبناء تطبيق ويب</a>
		<ul>
<li>
				<a href="#p21" rel="">بناء تطبيق نموذجي باستخدام Yeoman</a>
			</li>
			<li>
				<a href="#p22" rel="">ماذا لدينا في هذه الورشة؟</a>
			</li>
			<li>
				<a href="#p23" rel="">الخطوة 1: إعداد بيئة التطوير الخاصة بك</a>
			</li>
			<li>
				<a href="#p24" rel="">الخطوة 2: تثبيت مولّد Yeoman</a>
			</li>
			<li>
				<a href="#p25" rel="">الخطوة 3: استخدام مولّد لتنصيب سقالة حول التطبيق وبناء هيكله</a>
			</li>
			<li>
				<a href="#p26" rel="">الخطوة 4: مراجعة بنية التطبيق الذي أنشأته بواسطة Yeoman</a>
			</li>
			<li>
				<a href="#p27" rel="">الخطوة 5: معاينة تطبيقك في المتصفح</a>
			</li>
			<li>
				<a href="#p28" rel="">الخطوة 6: اختبار التطبيق بواسطة Karma و Jasmine</a>
			</li>
			<li>
				<a href="#p29" rel="">الخطوة 7: الاستفادة من التخزين المحلي لحفظ المهام (todos)</a>
			</li>
			<li>
				<a href="#p210" rel="">الخطوة 8: الاستعداد لمرحلة الإنتاج</a>
			</li>
			<li>
				<a href="#p211" rel="">ختام الورشة، تهانينا!</a>
			</li>
		</ul>
</li>
	<li>
		<a href="#p30" rel="">المصادر</a>
	</li>
</ul>
<h2 id="p10">
	الجزء الأول: البدء مع Yeoman
</h2>

<p>
	يُعدُّ <code>yo</code> أداة سطر الأوامر في Yeoman التي تسمح بإنشاء مشاريع باستخدام قوالب السقالات (scaffolding templates، يشار إليها باسم «المولدات» [generators]). يُثبَّت <code>yo</code> والمولدات المستخدمة باستعمال <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-nodejs-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r419/" rel="">مدير حزم نود</a> (npm).
</p>

<h3 id="p11">
	تثبيت <code>yo</code> وبعض المولدات
</h3>

<p>
	تأكد بدايةً من تثبيت Node.js ومدير حزمه npm على حاسوبك. نفِّذ الأمر التالي للتأكد من وجود Node.js و npm لديك:
</p>

<pre class="ipsCode">
$ nodejs -v
v8.10.0
</pre>

<pre class="ipsCode">
$ npm -v
3.5.2
</pre>

<p>
	ننصحك بالرجوع إلى مقال <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-nodejs-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r419/" rel="">تثبيت Node.js على نظام أبونتو</a> لمزيد من المعلومات حول عملية التثبيت على نظام لينكس. أمَّا على نظام ويندوز، نقترح استخدام أداة سطر أوامر أفضل مثل <a href="http://cmder.net" rel="external nofollow"><code>cmder</code></a> أو PowerShell لتجربة أفضل. يمكنك دومًا الرجوع إلى <a href="https://nodejs.org/en/download/" rel="external nofollow">موقع Node.js الرسمي</a> واختيار نوع نظام التشغيل لتثبيت <a href="https://wiki.hsoub.com/Node.js" rel="external">Node.js</a> و npm عليه.
</p>

<p>
	ثبِّت بعد ذلك <code>yo</code> باستخدام <code>npm</code> عبر الأمر التالي:
</p>

<pre class="ipsCode">
npm install -g yo
</pre>

<p>
	بعد ذلك، تُثبَّت المولد(ات) اللازم(ة)، والتي تكون عبارة عن حزم npm تسمى بالشكل <code>generator-XYZ</code>، إذ <code>XYZ</code> هو اسم المولِّد. ابحث عنها على في <a href="https://yeoman.io/generators/" rel="external nofollow">هذه الصفحة</a> أو عن طريق تحديد خيار قائمة "تثبيت مولد" (install a generator) أثناء في سطر الأوامر <code>yo</code>. إن أردت تثبيت المولد <code>webapp</code> مثلًا، نفِّذ الأمر التالي:
</p>

<pre class="ipsCode">
npm install -g generator-webapp
</pre>

<p>
	قد يواجه مستخدمو Node و npm الجدد مشكلات متعلقة بالأذونات. تظهر هذه المشكلات في شكل أخطاء <code>EACCESS</code> أثناء التثبيت. ارجع إلى <a href="https://docs.npmjs.com/getting-started/fixing-npm-permissions" rel="external nofollow">دليل npm لإصلاح الأذونات</a> إذا حدث لك هذا.
</p>

<h3 id="p12">
	تنصيب السقالة واستخدامها عمليًا
</h3>

<p>
	سنستخدم المولِّد <code>generator-webapp</code> الذي ثبَّتناه للتو في أمثلتنا أدناه. استبدل بالاسم <code>webapp</code> (الذي هو <code>XYZ</code>) اسم المولد الخاص بك للحصول على نفس النتيجة.
</p>

<p>
	من أجل تنصيب السقالة في مشروعك الجديد، نفِّذ الأمر التالي:
</p>

<pre class="ipsCode">
yo webapp
</pre>

<p>
	ستطرح أغلب المولّدات مجموعة من الأسئلة من أجل تخصيص المشروع الجديد؛ هل تذكر المواصفات والمعايير التي أخبرتك آنفًا بها لتخصيص بها مشروعك؟ ها هي عمليًا. لمعرفة الخيارات المتاحة، استخدم أمر المساعدة :
</p>

<pre class="ipsCode">
yo webapp --help
</pre>

<p>
	تعتمد الكثير من المولدات على أنظمة البناء (تعرف بأنها «أدوات بناء» أيضًا) مثل <a href="https://gulpjs.com/" rel="external nofollow">Gulp</a> أو <a href="http://gruntjs.com/" rel="external nofollow">Grunt</a>، ومديري الحزم مثل <a href="https://www.npmjs.com/" rel="external nofollow">npm</a> و <a href="https://bower.io/" rel="external nofollow">Bower</a>. تأكد من زيارة موقع المولّد لتتعلّم كيفية تشغيل التطبيق الجديد وصيانته. يمكنك الوصول بسهولة إلى الصفحة الرئيسية للمولّد بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode">
npm home generator-webapp
</pre>

<p>
	من المرجّح أن توفر إطارات العمل المعقدة للسقالات مولدات إضافية لبناء الأجزاء الصغيرة من المشروع. يشار إلى هذه المولدات عادةً بالمولدات الفرعية (sub-generators)، ويمكن الوصول إليها كما يلي: <code>generator:sub-generator</code>.
</p>

<p>
	لنأخذ المولِّد <code>generator-angular</code> مثالًا. يمكن بمجرد إنشاء تطبيق angular بالكامل إضافة ميزات أخرى. لإضافة وحدة تحكم جديدة إلى المشروع، شغِّل المولد الفرعي لوحدة التحكم:
</p>

<pre class="ipsCode">
yo angular:controller MyNewController
</pre>

<p>
	أي أن عمل السقالة لا تقتصر على بناء التطبيق توليد ملفاته الأولية، بل إضافة مزايا وعناصر إليه.
</p>

<h3 id="p13">
	أوامر <code>yo</code> الأخرى
</h3>

<p>
	بخلاف الأساسيات التي غطّيناها في القسم السابق، يعد <code>yo</code> أيضًا أداة تفاعلية بالكامل. ستوفر كتابة <code>yo</code> ببساطة في الطّرفية قائمة من الخيارات لإدارة كل ما يتعلق بالمولدات: التشغيل والتحديث والتثبيت والمساعدة وغيرها من الأدوات.
</p>

<p>
	تُوفّر<code>yo</code> أيضا الأوامر التالية:
</p>

<ul>
<li>
		<code>yo --help</code>: تمكنك من الوصول إلى شاشة المساعدة الكاملة
	</li>
	<li>
		<code>yo --generators</code>: تعطي قائمة بكل المولدات المثبتة
	</li>
	<li>
		<code>yo --version</code>: للحصول على الإصدار
	</li>
</ul>
<h3 id="p14">
	استكشاف الأخطاء وإصلاحها
</h3>

<p>
	يمكن إيجاد معظم المشكلات بتنفيذ الأمر:
</p>

<pre class="ipsCode">
yo doctor
</pre>

<p>
	سيشخِّص الأمر <code>doctor</code> خطوات لحلّ المشكلات الأكثر شيوعًا.
</p>

<h2 id="p20">
	الجزء الثاني: تنصيب سقالة Yeoman لبناء تطبيق ويب
</h2>

<p>
	أصبحت الآن جاهزًا لبناء تطبيق ويب كامل الوظائف من البداية بالاستعانة بمنصة Yeoman و FountainJS. سيُكتَب نموذج التطبيق في <a href="https://wiki.hsoub.com/React/" rel="external">React</a> أو <a href="https://angularjs.org/" rel="external nofollow">Angular1</a> أو <a href="https://angular.io/" rel="external nofollow">Angular2</a>.
</p>

<p>
	ليس لديك أي فكرة عن React أو Angular؟ لا بأس، سوف نرشدك. ومع ذلك، فإننا نفترض أن لديك تجربة سابقة مع لغة <a href="https://wiki.hsoub.com/JavaScript" rel="external">جافاسكريبت</a>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32317" href="https://academy.hsoub.com/uploads/monthly_2019_11/yeoman-008.cfa02809bf.png.13da8e37a4d79339bef2d369884a7bae.png" rel=""><img alt="yeoman-008.cfa02809bf.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32317" data-unique="7jlzm6lwo" src="https://academy.hsoub.com/uploads/monthly_2019_11/yeoman-008.cfa02809bf.thumb.png.a85dcf1a97afc56d72ef146bb52276fa.png"></a>
</p>

<h3 id="p21">
	بناء تطبيق نموذجي باستخدام Yeoman
</h3>

<p>
	سيكون نموذج تطبيق الويب الذي ستنشئه تنفيذًا لمشروع إطار عمل يسمى <a href="http://todomvc.com" rel="external nofollow">TodoMVC</a>. ستتمكن من إضافة عناصر مهام لإنجازها (todos) أوحذفها، أو ترشيحها، وسنضيف معًا ميزة لحفظها في وضع عدم الاتصال.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32309" href="https://academy.hsoub.com/uploads/monthly_2019_11/FinishedTodoMVC.png.1c16149371d7ad5e7e82750a75e18464.png" rel=""><img alt="FinishedTodoMVC.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32309" data-unique="9f9hkkfbv" src="https://academy.hsoub.com/uploads/monthly_2019_11/FinishedTodoMVC.thumb.png.3bab4d018064f87a7308040b5288c153.png"></a>
</p>

<h3 id="p22">
	ماذا لدينا في هذه الورشة؟
</h3>

<p>
	سنبني تطبيق TodoMVC أعلاه من الصفر. كل خطوة سوف تُبنَى على التي تسبقها، لذلك سننتقل من خلال كل خطوة تلو الأخرى:
</p>

<ul>
<li>
		<a href="#p23" rel="">الخطوة 1: إعداد بيئة التطوير الخاصة بك</a>
	</li>
	<li>
		<a href="#p24" rel="">الخطوة 2: تثبيت مولّد Yeoman</a>
	</li>
	<li>
		<a href="#p25" rel="">الخطوة 3: استخدام مولّد لتنصيب سقالة حول التطبيق وبناء هيكله</a>
	</li>
	<li>
		<a href="#p26" rel="">الخطوة 4: مراجعة بنية التطبيق الذي أنشأته بواسطة Yeoman</a>
	</li>
	<li>
		<a href="#p27" rel="">الخطوة 5: معاينة تطبيقك في المتصفح</a>
	</li>
	<li>
		<a href="#p28" rel="">الخطوة 6: اختبار التطبيق بواسطة Karma و Jasmine</a>
	</li>
	<li>
		<a href="#p29" rel="">الخطوة 7: الاستفادة من التخزين المحلي لحفظ المهام (todos)</a>
	</li>
	<li>
		<a href="#p210" rel="">الخطوة 8: الاستعداد لمرحلة الإنتاج</a>
	</li>
</ul>
<p>
	سوف تستغرق هذه الخطوات حوالي 25 دقيقة لإتمامها. في الختام، سيكون لديك تطبيق TodoMVC أنيق وسوف يكون جهاز حاسوبك معدًّا لإنشاء المزيد من تطبيقات الويب الرائعة في المستقبل.
</p>

<p>
	جاهز؟ لنبدأ مع الخطوة الأولى!
</p>

<h3 id="p23">
	الخطوة 1: إعداد بيئة التطوير الخاصة بك
</h3>

<p>
	ستكون معظم تفاعلاتك مع Yeoman عبر سطر الأوامر. نفّذ الأوامر في الطّرفية إذا كنت تستخدم نظام التشغيل Mac أو في الصدفة <code>shell</code> في نظام لينكس أو في واجهة <a href="http://cmder.net/" rel="external nofollow"><code>cmder</code></a> (وهي المفضلة) أو PowerShell أو <code>cmd.exe</code> إذا كنت تستخدم نظام التشغيل ويندوز.
</p>

<h4>
	تثبيت المتطلبات الأساسية
</h4>

<p>
	قبل تثبيت <code>Fountain Webapp Generator</code>، ستحتاج إلى ما يلي:
</p>

<ul>
<li>
		الإصدار السادس من <code>Node.js</code> أو ما بعده.
	</li>
	<li>
		الإصدار الثالث من <code>npm</code> أو ما بعده (والذي يأتي مرفقًا مع <code>Node</code>)
	</li>
	<li>
		نظام التحكم بالإصدارات <code>Git</code>
	</li>
</ul>
<p>
	يمكنك أن تتحقق مما إذا كان لديك Node و npm مثبتين بكتابة ما يلي:
</p>

<pre class="ipsCode">
node --version &amp;&amp; npm --version
</pre>

<p>
	إذا كنت بحاجة إلى ترقية Node أو تثبيته، فإن أسهل طريقة هي استخدام المثبت في نظامك الأساسي. نزِّل حزمة "msi." بالنسبة لنظام ويندوز أو "pkg." لنظام التشغيل Mac من موقع <a href="https://nodejs.org/" rel="external nofollow">NodeJS</a> ثم ثبِّتها. وإذا كنت تستخدم نظام لينكس، يمكنك تنزيل أحدث إصدار من <a href="https://nodejs.org/en/download/" rel="external nofollow">صفحة التنزيل في الموقع الرسمي</a>.
</p>

<p>
	يكون مدير الحزم <a href="https://www.npmjs.com/" rel="external nofollow">npm</a> مدمجًا مع Node، رغم أنّك قد تحتاج إلى تحديثه. وتأتي بعض إصدارات Node مع الإصدارات القديمة بدلاً من npm. يمكنك تحديث npm باستخدام هذا الأمر:
</p>

<pre class="ipsCode">
npm install --global npm@latest
</pre>

<p>
	يمكنك التحقق من تثبيت Git من خلال كتابة ما يلي:
</p>

<pre class="ipsCode">
git --version
</pre>

<p>
	إذا لم يكن لديك Git، حمّل أداة التثبيت من <a href="https://git-scm.com/" rel="external nofollow">الموقع الرسمي</a>. إن كان نظام التشغيل لديك هو أحد توزيعات ديبيان من لينكس، فنفِّذ الأمر التالي لتثبيت Git:
</p>

<pre class="ipsCode">
sudo apt install git
</pre>

<h4>
	تثبيت أدوات Yeoman
</h4>

<p>
	بمجرد تثبيت Node، ثَبِّت أيضًا مجموعة أدوات Yeoman عبر تنفيذ الأمر التالي:
</p>

<pre class="ipsCode">
npm install --global yo
</pre>

<h4>
	هل هناك أخطاء؟
</h4>

<p>
	إذا واجهت أي أخطاء في الأذونات أو الوصول، مثل خطأ <code>EPERM</code> أو <code>EACCESS</code>، فلا تستخدم <code>sudo</code> كحلّ بديل. تستطيع الاستفادة من <a href="https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md" rel="external nofollow">هذا الدليل</a>. ويمكنك أيضًا الإطلاع على <a href="https://academy.hsoub.com/devops/linux/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-nodejs-%D8%B9%D9%84%D9%89-%D9%86%D8%B8%D8%A7%D9%85-%D8%A3%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r419/" rel="">هذا المقال</a> لمعلومات أوسع حول عملية التثبيت.
</p>

<h4>
	التحقق من نجاح عملية التثبيت
</h4>

<p>
	من المستحسن التحقق من تثبيت كل شيء كما هو متوقع عبر تنفيذ أوامر Yeoman شائعة الاستخدام مثل <code>yo</code> مع الراية <code>version--</code> كالتالي:
</p>

<pre class="ipsCode">
yo --version
</pre>

<h4>
	إصدارات أدوات CLI التي تعمل معها هذه الورشة البرمجية
</h4>

<p>
	تتغير التكنولوجيا بسرعة! لقد نُفِّذت هذه الورشة التعليمية باستخدام الإصدار 1.8.4 من سطر الأوامر <code>yo</code>. إذا كنت تواجه مشكلات في إصدار أحدث، فسيسعدنا أن نعرف عنها. يمكنك <a href="https://help.github.com/en/articles/submitting-a-ticket" rel="external nofollow">فتح تذكرة في GitHub</a> للإبلاغ بأي مشكلة.
</p>

<h3 id="p24">
	الخطوة 1: تثبيت مولد Yeoman
</h3>

<p>
	ستحتاج في سير عمل تطوير الويب التقليدي إلى قضاء الكثير من الوقت في إعداد الشيفرة المتداولة (boilerplate code) الخاص بتطبيق الويب الذي تعمل عليه، وتنزيل التبعيات، وإنشاء بنية مجلد الويب الخاصة بك يدويًا. ولكن مولّدات Yeoman ستسهّل عليك المهمّة كثيرًا! لنثبِّت مولّدًا لمشاريع FountainJS.
</p>

<h4>
	تثبيت المولّد
</h4>

<p>
	يمكنك تثبيت مولدات Yeoman باستخدام الأمر <a href="https://www.npmjs.com/" rel="external nofollow">npm</a> وهناك أكثر من <a href="https://yeoman.io/generators/" rel="external nofollow">3500 مولد</a> متاح الآن، وكثير منها كتبه أفراد مجتمع المصادر المفتوحة.
</p>

<p>
	ثبِّت المُولِّد <a href="https://www.npmjs.com/package/generator-fountain-webapp" rel="external nofollow">generator-fountain-webapp</a> باستخدام هذا الأمر:
</p>

<pre class="ipsCode">
npm install --global generator-fountain-webapp
</pre>

<p>
	سيبدأ هذا بتثبيت حزم Node المطلوبة للمولد.
</p>

<p>
	<strong>تذكير</strong>: إذا واجهت أي أخطاء في الأذونات أو الوصول، مثل خطأ <code>EPERM</code> أو <code>EACCESS</code>، فلا تستخدم <code>sudo</code> كحلّ بديل. تستطيع الاستفادة من <a href="https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md" rel="external nofollow">هذا الدليل</a>.
</p>

<p style="text-align: center;">
	في الوقت الذي تستخدم فيه <code>npm install</code> مباشرة، يمكنك البحث عن المولدات عبر قائمة Yeoman التفاعلية. نفِّذ الأمر <code>yo</code> وحدِّد <strong>Install a generator</strong> للبحث عن المولدات المنشورة. <img alt="yointeractive.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32320" data-unique="qdpkdmr1h" src="https://academy.hsoub.com/uploads/monthly_2019_11/yointeractive.png.357cca2cb54f62e94c3cfacc5f8d6beb.png"></p>

<h3 id="p25">
	الخطوة 3: استخدام مولّد لتنصيب سقالة حول التطبيق وبناء هيكله
</h3>

<p>
	لقد استخدمنا كلمة «سقالة» مرات عديدة وشرحنا معناها في بداية هذا الدليل لكن قد ما تزال غريبة بعض الشيء. تعني السقالة، بالمفهوم المستخدم في Yeoman للكلمة (وفي عالم البرمجة عمومًا)، إنشاء ملفات لتطبيق الويب الخاص بك وفق معايير ومواصفات تضبطها أنت. سترى في هذه الخطوة كيف يمكن لـ Yeoman إنشاء ملفات خاصة بمكتبتك أو إطارك المفضل، مع خيارات لاستخدام مكتبات خارجية أخرى مثل Webpack و Babel و SASS وربطها بمشروعك، بأقل جهد ممكن.
</p>

<h4>
	إنشاء مجلد المشروع
</h4>

<p>
	أنشئ مجلدًا باسم <code>mytodo</code> ليحوي جميع ملفات المشروع الذي سنعمل على بنائه:
</p>

<pre class="ipsCode">
mkdir mytodo &amp;&amp; cd mytodo
</pre>

<p>
	هذا المجلد هو المكان الذي سيولِّد المولد فيه ملفات مشروعك الابتدائية (أي هيكل المشروع).
</p>

<h4>
	الوصول للمولدات عبر قائمة Yeoman
</h4>

<p>
	نفِّذ الأمر <code>yo</code> لرؤية المولدات الخاصة بك:
</p>

<pre class="ipsCode">
yo
</pre>

<p>
	إذا كان لديك عدد قليل من المولدات المثبتة، فستتمكن من الاختيار بشكل تفاعلي منها. اختر المُولِّد <strong>Fountain Webapp</strong> لتشغيله.
</p>

<p style="text-align: center;">
	<img alt="yointeractive03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32321" data-unique="ydourzcvh" src="https://academy.hsoub.com/uploads/monthly_2019_11/yointeractive03.png.3b99d3be280ff7ef36a007db99bf259a.png"></p>

<h4>
	استخدام المولدات مباشرة
</h4>

<p>
	عندما تستأنس أكثر بسطر الأوامر <code>yo</code>، ستفضّل تشغيل المولِّد مباشرةً دون استخدام القائمة التفاعلية (وضغط المزيد من الأزرار) على النحو التالي:
</p>

<pre class="ipsCode">
yo fountain-webapp
</pre>

<h4>
	إعداد المولد الخاص بك
</h4>

<p>
	توفر بعض المولدات إعدادات اختيارية لتخصيص تطبيقك مع مكتبات مطوّري البرامج المشتركة لتسريع الإعداد الأولي لبيئة التطوير الخاصة بك.
</p>

<p>
	يوفر المولد FountainJS بعض الخيارات لكي تستخدم ما تفضله:
</p>

<ul>
<li>
		إطار العمل (<a href="https://wiki.hsoub.com/React" rel="external">React</a> أو <a href="https://angular.io/" rel="external nofollow">Angular2</a> أو <a href="https://angularjs.org/" rel="external nofollow">Angular1</a>)
	</li>
	<li>
		وحدة الإدارة (<a href="https://webpack.github.io/" rel="external nofollow">Webpack</a> أو [SystemJS] أو لا شيء إذا كنت تستعمل Bower)
	</li>
	<li>
		معالج أولي لشيفرة جافاسكربت (Babel أو TypeScript أو لا شيء)
	</li>
	<li>
		معالج أولي لشيفرة <a href="https://wiki.hsoub.com/CSS" rel="external">CSS</a> ‏(<a href="https://wiki.hsoub.com/Sass" rel="external">SASS</a> أو LESS أو لا شيء)
	</li>
	<li>
		ثلاثة نماذج للتطبيق (<a href="https://academy.hsoub.com/tags/landing%20page%20101/" rel="">صفحة هبوط</a> وصفحة "مرحبا بالعالم" [hello world] ونموذج TodoMVC)
	</li>
</ul>
<p>
	سوف نستخدم لهذه الورشة الخيارات التالية:
</p>

<ul>
<li>
		React
	</li>
	<li>
		Webpack
	</li>
	<li>
		Babel
	</li>
	<li>
		SASS
	</li>
	<li>
		نموذج Redux TodoMVC
	</li>
</ul>
<p>
	 
</p>

<p>
	حدّد هذه الخيارات على التوالي باستخدام مفاتيح الأسهم ثم زر "إدخال" واستمتع بما يحدث على الشاشة.
</p>

<p style="text-align: center;">
	<img alt="yoselect03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32323" data-unique="xsxqiejsu" src="https://academy.hsoub.com/uploads/monthly_2019_11/yoselect03.png.97201a29681ebd17834e3460bd3ccbdf.png"></p>

<p>
	سيبني Yeoman تلقائيًا هيكل تطبيقك ويولد لك جميع الملفات الابتدائية الأساسية له، وسيجلب كل الاعتماديات (dependencies) الخاصة به. بعد بضع دقائق، سنكون مستعدين للانتقال إلى الخطوة التالية.
</p>

<p style="text-align: center;">
	<img alt="yoend03.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32319" data-unique="tlr2hpw3u" src="https://academy.hsoub.com/uploads/monthly_2019_11/yoend03.png.614d7347e9e7725e2281ccfc9e58eebc.png"></p>

<h3 id="p26">
	الخطوة 4: مراجعة التطبيق الذي بناه Yeoman
</h3>

<p>
	افتح المجلّد <code>mytodo</code> الخاص بك لإلقاء نظرة على ما جرى بناؤه إلى الآن. يجب أن يبدو مثلما توضحه الصورة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32316" href="https://academy.hsoub.com/uploads/monthly_2019_11/treeview04.png.fc0a7c5e4ead85ace7673265295cdf15.png" rel=""><img alt="treeview04.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32316" data-unique="xbdnizwxp" src="https://academy.hsoub.com/uploads/monthly_2019_11/treeview04.thumb.png.fd4027061663d1386d0d77a7888e7b95.png"></a>
</p>

<p>
	لدينا في مجلد المشروع المجلدات الفرعية التالية:
</p>

<ul>
<li>
		<code>src</code>: مجلّد رئيسي لتطبيق الويب

		<ul>
<li>
				<code>app</code>: شيفرة React و Redux
			</li>
			<li>
				<code>index.html</code>: ملف html الرئيسي
			</li>
			<li>
				<code>index.js</code>: نقطة الدخول لتطبيق TodoMVC
			</li>
		</ul>
</li>
	<li>
		<code>conf</code> : مجلّد رئيسي لملفات الضبط الخاصة بالأدوات الخارجية (Browsersync و Webpack و Gulp و Karma)
	</li>
	<li>
		<code>gulp_tasks</code> و <code>gulpfile.js</code>: مهام أداة البناء <a href="https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%A3%D8%AF%D8%A7%D8%A9-%D8%A7%D9%84%D8%A8%D9%86%D8%A7%D8%A1-gulp-r663/" rel="">Gulp</a>
	</li>
	<li>
		<code>babelrc.</code> و <code>package.json</code> و <code>node_modules</code>: الضبط والاعتماديات المطلوبة
	</li>
	<li>
		<code>gitattributes.</code> و <code>gitignore.</code>: ملفات ضبط Git
	</li>
</ul>
<h4>
	أنشِئ الإيداع (commit) الأول في المستودع
</h4>

<p>
	الآن وبعد التوليد والتثبيت، يجب أن يكون لديك مستودع git جديد مهيأ بالفعل. يمكنك الإيداع فيه بأمان لحفظ الحالة الراهنة من خلال هذه الأوامر:
</p>

<pre class="ipsCode">
git add --all &amp;&amp; git commit -m 'First commit'
</pre>

<h3 id="p27">
	الخطوة 5: استعرض تطبيقك في متصفّح الويب
</h3>

<p>
	إن أردت معاينة تطبيق الويب الخاص بك في متصفحك المفضل، ليس عليك القيام بأي شيء خاص لإعداد خادم ويب محلي على جهاز حاسوبك، فهو جزء من مهام Yeoman.
</p>

<h4>
	تشغيل الخادم
</h4>

<p>
	شغّل سكربت npm لإنشاء خادم http محلي يستند إلى Node على <a href="http://localhost:3000/" rel="external nofollow">localhost:3000</a> (أو <a href="http://127.0.0.1:3000/" rel="external nofollow">127.0.0.1:3000</a> بالنسبة لبعض التكوينات) بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode">
npm run serve
</pre>

<p>
	افتح لسانًا جديدًا في متصفحك وانتقل إلى العنوان <a href="http://localhost:3000/" rel="external nofollow">3000:localhost</a>:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32312" href="https://academy.hsoub.com/uploads/monthly_2019_11/runpreview05.png.c61843b17ff07fa9d5ea40e505ac1338.png" rel=""><img alt="runpreview05.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32312" data-unique="q4yd4jbu9" src="https://academy.hsoub.com/uploads/monthly_2019_11/runpreview05.thumb.png.c012cc1ac038fba87b5617f439fa2f11.png"></a>
</p>

<h4>
	إيقاف الخادم
</h4>

<p>
	إذا احتجت في أي وقت إلى إيقاف الخادم، فاستخدم الاختصار Ctrl + C لإنهاء عملية سطر الأوامر الحالية.
</p>

<p>
	<strong>ملاحظة</strong>: لا يمكنك تشغيل أكثر من خادم http واحد على نفس المنفذ (3000 افتراضيًا).
</p>

<h4>
	مراقبة ملفاتك
</h4>

<p>
	افتح محرر النصوص الذي تفضّله وابدأ في إجراء التغييرات. سيفرض كل حفظِ لملفاتك تحديث المتصفح تلقائيًا إذ لا يتعين عليك القيام بذلك بنفسك. يُطلق على هذا إعادة التحميل المباشر وهي طريقة رائعة لتعاين حالة تطبيقك في الوقت الفعلي وعكس التغييرات مباشرةً على المتصفح دون أن تفعل أي شيء.
</p>

<p>
	تُوَّفر لتطبيقك عملية إعادة التحميل المباشر (Live reloading) من خلال مجموعة من مهام Gulp التي يتم إعدادها في الملف <code>gulpfile.js</code> و <a href="https://www.browsersync.io/" rel="external nofollow">Browsersync</a> التي يتم إعدادها في الملف <code>gulp_tasks/browsersync.js</code>؛ فهي تراقب التغييرات التي تطرأ على ملفاتك وتعيد تحميلها تلقائيًا في المتصفح في حالة اكتشاف تغيير ما.
</p>

<p>
	فيما يلي أدناه، حرّرنا الملف <code>Header.js</code> القابع في المجلّد <code>src/app/components.</code> بفضل التحديث المباشر، تظهر التغييرات مباشرةً في المتصفح وهذه صورة قبل إجراء أي تعديل:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32308" href="https://academy.hsoub.com/uploads/monthly_2019_11/beforereload05.png.ddc3424bba05f28ccd46f7e32a7058f7.png" rel=""><img alt="beforereload05.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32308" data-unique="y3mezc63z" src="https://academy.hsoub.com/uploads/monthly_2019_11/beforereload05.thumb.png.0dc8057cb966cbd009b318f87e0619ab.png"></a>
</p>

<p>
	وصورة بعد إجراء تعديل (تغيير عنوان التطبيق) وحفظ الملف:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32306" href="https://academy.hsoub.com/uploads/monthly_2019_11/afterreload05.png.74dbba41b4a7e02bec11b4d1ba7fe0df.png" rel=""><img alt="afterreload05.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32306" data-unique="uxi9rasmw" src="https://academy.hsoub.com/uploads/monthly_2019_11/afterreload05.thumb.png.df75a634b1ce0107ee089229731351cf.png"></a>
</p>

<h4>
	لا تنس الاختبار!
</h4>

<p>
	لديك تطبيق TodoMVC مجرّب وأنت تقوم بتغيير العنوان. يتعيّن عليك تعديل الاختبار في mytodo/src/app/<code>components/Header.spec.js</code> أو التراجع عن التغيير للتثبت من عملية إعادة التحميل المباشر.
</p>

<h3 id="p28">
	الخطوة 6: الاختبار باستخدام Karma و Jasmine
</h3>

<p>
	إذا لم يكن <a href="http://karma-runner.github.io" rel="external nofollow">Karma</a> مألوفًا لديك، فهو برنامج اختبار شيفرات جافاسكربت أي إطار عمل محايد للاختبار. أمّا إطار الاختبار <a href="http://jasmine.github.io" rel="external nofollow">Jasmine</a> فهو مدمج في المولد fountainjs. عندما نفّذنا الأمر <code>yo fountain-webapp</code> في وقت سابق من هذا الدليل، قام المولد بتوليد الملفات ذات النمط <code>spec.js.*</code> في المجلد المصدري لمجلد المشروع <code>mytodo</code>، وأنشأ الملف <code>conf/karma.conf.js</code>، ثم سحب وحدات Node إلى Karma. سنحرّر سكربت Jasmine لوصف الاختبارات قريبًا ولكن دعنا نرى كيف يمكننا إجراء الاختبارات أولًا.
</p>

<h4>
	تشغيل اختبارات الوحدة
</h4>

<p>
	دعنا نعود إلى سطر الأوامر ونوقف الخادم المحلي قسرًا باستخدام الاختصار Ctrl + C. يوجد بالفعل سكربت npm أُدرِج في الملف <code>package.json</code> الخاص بنا لإجراء الاختبارات. يمكن تشغيله على النحو التالي:
</p>

<pre class="ipsCode">
npm test
</pre>

<p>
	ينبغي أن تنجح جميع الاختبارات.
</p>

<h4>
	تحديث اختبارات الوحدة
</h4>

<p>
	ستجد اختبارات الوحدة مهيّأة في المجلد <code>src</code>، لذلك افتح الملف src/app/reducers/todos.spec.js. هذا هو اختبار الوحدة للمخفض (reducer) الخاص بـ Todos. على سبيل المثال، نركز على الاختبار الأول الذي يتحقق من الحالة الابتدائية. (ملاحظة: على ويندوز، قد تحتاج إلى إضافة <code>127.0.0.1 localhost</code> إلى الملف <code>etc/hosts</code>):
</p>

<pre class="ipsCode">
it('should handle initial state', () =&gt; {
  expect(todos(undefined, {})).toEqual([
    {
      text: 'Use Redux',
      completed: false,
      id: 0
    }
  ]);
});
</pre>

<p>
	واستبدل هذا الاختبار بما يلي:
</p>

<pre class="ipsCode">
it('should handle initial state', () =&gt; {
  expect(todos(undefined, {})).toEqual([
    {
      text: 'Use Yeoman', // &lt;=== هنا
      completed: false,
      id: 0
    }
  ]);
});
</pre>

<p>
	عندما نعيد تنفيذ الاختبارات عبر الأمر <code>npm test</code>، ينبغي أن نرى أن الاختبارات تفشل في هذه الحالة.
</p>

<p>
	<strong>ملاحظة</strong>: إذا كنت تريد تشغيل الاختبارات تلقائيًا بعد إجراء أي تعديل، يمكنك استخدام <code>npm run test:auto</code> بدلًا من ذلك.
</p>

<p>
	افتح <code>src/app/reducers/todos.js</code> ثم ضع الشيفرة التالية مكان الحالة الابتدائية (initial state):
</p>

<pre class="ipsCode">
const initialState = [
  {
    text: 'Use Yeoman',
    completed: false,
    id: 0
  }
];
</pre>

<p>
	رائع! لقد أصلحت الاختبار:
</p>

<p style="text-align: center;">
	<img alt="runtest06.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32313" data-unique="i5kg9qwxw" src="https://academy.hsoub.com/uploads/monthly_2019_11/runtest06.png.2cae369c8fa991c3844fc3fc94f721cf.png"></p>

<p>
	تسهِّل كتابة اختبارات الوحدة (unit tests) تحديد الأخطاء كلّما أصبح تطبيقك أكبر فأكبر وكلّما انضمّ المزيد من المطورين إلى فريقك. تجعل ميزة الاعتماد على السقالة (scaffolding) في Yeoman كتابة اختبارات الوحدة أسهل، لذا لن يكون لك عذر إذا لم تكتب اختباراتك بيديك! ;-)
</p>

<h3 id="p29">
	الخطوة 7: الاستفادة من التخزين المحلي لحفظ المهام (todos)
</h3>

<p>
	دعنا نعيد النظر في مشكلة العناصر التي لا تثبت (تعاد إلى حالتها الأولية) عندما يُحدَّث المتصفح من خلال تطبيق mytodo مع React/Redux.
</p>

<p>
	<strong>تنويه</strong>: إذا لم يكن الثبات والتخزين المحلي مشكلةً بالنسبة لك أو كان وقتك ضيقًا، فيمكنك تخطي هذه الخطوة والانتقال مباشرة إلى <a href="#p210" rel="">الخطوة 8</a>، "الاستعداد للإنتاج".
</p>

<h4>
	تثبيت حزمة npm
</h4>

<p>
	يمكننا استخدام وحدة Redux أخرى تسمى "redux-localstorage" تتيح لنا تنفيذ التخزين المحلي بسرعة وسهولة. نفِّذ الأمر التالي لتثبيتها:
</p>

<pre class="ipsCode">
npm install --save redux-localstorage@rc
</pre>

<p style="text-align: center;">
	<img alt="install07.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32310" data-unique="f12w8re64" src="https://academy.hsoub.com/uploads/monthly_2019_11/install07.png.039613fdfb04c7c81fd9d4ed2da23b6b.png"></p>

<h4>
	استخدام redux-localstorage
</h4>

<p>
	يجب إعداد مخزن Redux وضبطه لاستخدام التخزين. افتح الملف <code>src/app/store/configStore.js</code> واحذف كل محتواه وضع الشيفرة التالي مكانه:
</p>

<pre class="ipsCode">
import {compose, createStore} from 'redux';
import rootReducer from '../reducers';

import persistState, {mergePersistedState} from 'redux-localstorage';
import adapter from 'redux-localstorage/lib/adapters/localStorage';

export default function configureStore(initialState) {
  const reducer = compose(
    mergePersistedState()
  )(rootReducer, initialState);

  const storage = adapter(window.localStorage);

  const createPersistentStore = compose(
    persistState(storage, 'state')
  )(createStore);

  const store = createPersistentStore(reducer);
  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../reducers', () =&gt; {
      const nextReducer = require('../reducers').default;
      store.replaceReducer(nextReducer);
    });
  }

  return store;
}
</pre>

<p>
	إذا عاينت تطبيقك في المتصفح، سترى أن هناك عنصرًا واحدًا "Use Yeoman" في قائمة مهام todo. يعمل التطبيق على تهيئة مخزن مهام todos إذا كانت مساحة التخزين المحلية فارغة ولم نضف فيها أي عناصر حتى الآن.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32307" href="https://academy.hsoub.com/uploads/monthly_2019_11/before07.png.44e6e74cb9116d23fef0eb2f39e7d7df.png" rel=""><img alt="before07.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32307" data-unique="7tkkyt371" src="https://academy.hsoub.com/uploads/monthly_2019_11/before07.thumb.png.10bbb075829cafaa8300ab7bb4843f1c.png"></a>
</p>

<p>
	جرب إضافة بعض العناصر إلى القائمة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32305" href="https://academy.hsoub.com/uploads/monthly_2019_11/after07.png.9a6ca5ded6c885be50de5b725e9add0b.png" rel=""><img alt="after07.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32305" data-unique="t8y71hdzo" src="https://academy.hsoub.com/uploads/monthly_2019_11/after07.thumb.png.de38c71777ae6a0286201a840b04875b.png"></a>
</p>

<p>
	الآن عندما تُحدِّث المتصفح، نلاحظ أن العناصر موجودة وثابتة. أمرٌ جيدٌ!
</p>

<p>
	يمكننا التأكّد من ثبات بياناتنا في التخزين المحلي عبر التحقق من لوحة الموارد (Resources) في <a href="https://academy.hsoub.com/programming/workflow/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D9%90%D9%91%D8%B1-devtools-%D9%81%D9%8A-chrome-r554/" rel="">أدوات المطور Chrome DevTools</a> واختيار Local Storage في الجانب الأيسر:
</p>

<p style="text-align: center;">
	<img alt="show07.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32315" data-unique="y0zhsybwd" src="https://academy.hsoub.com/uploads/monthly_2019_11/show07.png.ccd9c9f75f0dfc0f27eb0c2f7557d58f.png"></p>

<h4>
	اكتب اختبارات الوحدة
</h4>

<p>
	تريد تحديًا إضافيًا؟ حسنًا لك ذلك؛ أعد زيارة اختبارات الوحدة في <a href="#p28" rel="">الخطوة 6</a> وفكّر في كيفية تحديث اختباراتك الآن إذ تستخدم الشيفرة التخزين المحلي.
</p>

<h3 id="p210">
	الخطوة 8: الاستعداد لمرحلة الإنتاج
</h3>

<p>
	هل أنت مستعد لعرض تطبيقك الجميل؟ دعنا نحاول بناء نسخة جاهزة للإنتاج نستطيع تسليمها للعميل مثلًا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32318" href="https://academy.hsoub.com/uploads/monthly_2019_11/yeoman09.png.5f07bfeec61bb382b9f68de15d091d0e.png" rel=""><img alt="yeoman09.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32318" data-unique="d3852yb9l" src="https://academy.hsoub.com/uploads/monthly_2019_11/yeoman09.thumb.png.eb58c04baa611cd077c192e4a445ff0e.png"></a>
</p>

<h4>
	تحسين الملفات من أجل الإنتاج
</h4>

<p>
	لإنشاء نسخة نهائية من تطبيقنا، نحتاج إلى:
</p>

<ul>
<li>
		فحص الشيفرة بحثا عن أي أخطاء محتملة عبر الأداة lint.
	</li>
	<li>
		تجميع واختصار السكريبتات والأنماط الخاصة بنا لحفظها.
	</li>
	<li>
		تفسير أي مُخرَجات للمعالجات الأولية (preprocessors) التي نستخدمها.
	</li>
	<li>
		وإجمالًا جعل تطبيقنا رشيقًا.
	</li>
</ul>
<p>
	ما يثير الدهشة هو أننا نستطيع فعل كل ما سبق فقط بتنفيذ الأمر البسيط التالي:
</p>

<pre class="ipsCode">
npm run build
</pre>

<p>
	إنّ تطبيقك الرشيق الجاهز للإنتاج متوفرٌ الآن في المجلد <code>dist</code> في جذر مجلد المشروع <code>mytodo</code> الخاص بك. هذه هي الملفات التي يمكنك وضعها على خادمك باستخدام FTP أو أي خدمة نشر أخرى.
</p>

<h4>
	بناء ومعاينة التطبيق الجاهز للإنتاج
</h4>

<p>
	هل تريد معاينة تطبيقك الجاهز للإنتاج محليًا؟ إليك مجرد سكربت npm بسيط آخر:
</p>

<pre class="ipsCode">
npm run serve:dist
</pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32314" href="https://academy.hsoub.com/uploads/monthly_2019_11/serve08.png.952748437c12546d4eb9731912be73ab.png" rel=""><img alt="serve08.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32314" data-unique="ror52byq9" src="https://academy.hsoub.com/uploads/monthly_2019_11/serve08.thumb.png.8717352257b4b972fd8bde56d1d7af15.png"></a>
</p>

<p>
	سيعمل على بناء مشروعك وإطلاق خادم ويب محلي. إنّه رائع حقًّا!
</p>

<h3 id="p211">
	ختام الورشة، تهانينا!
</h3>

<p>
	كما ترى، يمكن أن يتيح لك Yeoman الكثير والمزيد من الأدوات الخيارات، فيدعم تنصيب السقالات بناء تطبيقات Angular وبعض الإطارات الأخرى التي لم نتطرق لها هنا.
</p>

<p>
	على سبيل المثال، يدعم مولد Fountain Angular كذلك إنشاء أنابيب (pipes) وتوجيهات (directives) وخدمات (services) ومكونات (components) جديدة لك. يمكن توليد مكونات جديدة ببساطة وسهولة عبر تنفيذ الأمر: <code>yo fountain-angular2:component componentName</code>، والذي سيؤدي إلى إنشاء ملف المكون الخاص بك وإضافة شيفرة <code>componentName.spec.js</code> جديدة لاختبار الوحدة أيضًا.
</p>

<h4>
	العثور على المزيد من المولدات الفرعية
</h4>

<p>
	يمكنك في أي وقت استخدام الأمر: <code>yo --generators</code> للاطلاع على جميع المولدات الفرعية لمولدات Yeoman المثبَّتة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32311" href="https://academy.hsoub.com/uploads/monthly_2019_11/list09.png.8b031ac32f34a03425b3dcbce318a959.png" rel=""><img alt="list09.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32311" data-unique="80ninpcky" src="https://academy.hsoub.com/uploads/monthly_2019_11/list09.thumb.png.fbea9003f63e7b97e7237ba6b56d37df.png"></a>
</p>

<h4>
	وماذا بعد ذلك؟
</h4>

<ul>
<li>
		Yeoman دائم التطور. احرص على زيارة الموقع <a href="https://yeoman.io/" rel="external nofollow">yeoman.io</a> للحصول على مزيد من المعلومات ومتابعة <a href="https://twitter.com/yeoman" rel="external nofollow">Yoman@</a> على تويتر لمواكبة المستجدات.
	</li>
	<li>
		ساعدتنا مولدات <a href="github.com/FountainJS" rel="">Fountain</a> على كتابة هذا التطبيق Todo بسرعة وأناقة. تابع <a href="https://twitter.com/yeomanfountain" rel="external nofollow">YeomanFountain@</a> للبقاء على اطلاع على الميزات الجديدة والإصدارات الجديدة.
	</li>
	<li>
		<a href="https://wiki.hsoub.com/React" rel="external">React</a> هو مكتبة جافا سكريبت لبناء واجهات المستخدم. اطلع على توثيق React في <a href="https://wiki.hsoub.com" rel="external">موسوعة حسوب</a> للتعرف على هذه المكتبة أكثر.
	</li>
	<li>
		<a href="angular.io" rel="">Angular2</a> إطار عمل للتطوير على كافة المنصّات.
	</li>
	<li>
		<a href="webpack.github.io" rel="">Webpack</a> عبارة عن وحدة مجمعة (module bundler) نموذجية تأخذ الوحدات النمطية ذات الاعتماديات وتولد أصول ثابتة (static assets) تمثل تلك الوحدات. *<a href="jspm.i" rel="">JSPM</a> حزمة إدارة متصفح. حمّل أي تنسيق للوحدة (ES، و AMD، و CommonJS، وglobals) مباشرة من أي سجل مثل npm و GitHub مع إدارة تبعية حديثة الإصدار (flat versioned dependency management).
	</li>
</ul>
<p>
	هذا كل ما ينبغي ذكره الآن بخصوص Yeoman.
</p>

<h2 id="p30">
	المصادر
</h2>

<ul>
<li>
		<a href="https://yeoman.io/learning/index.html" rel="external nofollow">Getting Started With Yeoman</a>
	</li>
	<li>
		<a href="https://yeoman.io/codelab/index.html" rel="external nofollow">Let's Scaffold A Web App With Yeoman</a>
	</li>
</ul>
<p>
	 
</p>
]]></description><guid isPermaLink="false">761</guid><pubDate>Thu, 07 Nov 2019 18:08:02 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644;&#x643; &#x625;&#x644;&#x649; &#x627;&#x633;&#x62A;&#x639;&#x645;&#x627;&#x644; &#x627;&#x644;&#x623;&#x62F;&#x627;&#x629; Lighthouse</title><link>https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A5%D9%84%D9%89-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%A7%D9%84%D8%A3%D8%AF%D8%A7%D8%A9-lighthouse-r691/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_06/5d062d7853509_lighthouse.png.5ef0ee7105547286436aa4c82677575f.png" /></p>

<p>
	Lighthouse هو أداة مُؤَتمتة (Automated) مفتوحة المصدر لتحسين صفحات الويب. يمكن تطبيق الأداة على أي صفحة ويب سواء كانت عامّة أو تحتاج للاستيثاق (Authentication). يمكن استخدام الأداة للتدقيق في الأداء، قابليّة الوصول (Accessibility)، صفحات الويب التقدميّة (Progressive web apps) وغيرها.
</p>

<p>
	تستطيع تشغيل Lighthouse من أدوات المُطوّر في Chrome أو سطر الأوامر أو بصيغة وحدة Node. تستقبل الأداة Lighthouse رابط URL لتدقيقه فتُشغِّل سلسلة من التدقيقات على الصفحة ثم تولّد تقريرًا عن حالة الصفحة. اعتمد على التقرير واستخدم التدقيقات التي أخفقت فيها الصفحة دليلا لكيفية تحسينها. يوجد في كلّ تدقيق توثيق مرجعي يشرح أهميّة التدقيق وكيف تصلح الصفحة لتتوافق معه.
</p>

<h2 id="-">
	البداية
</h2>

<p>
	اختر سير عمل Lighthouse الذي يناسبك:
</p>

<ul>
<li>
		أدوات التطوير في Chrome. دقّق الصفحات التي تحتاج الاستيثاق بسهولة واقرأ التقارير بصيغة مفهومة للمستخدم.
	</li>
	<li>
		عبر سطر الأوامر. أتمت تشغيلات Lighthouse بسكربتات Shell.
	</li>
	<li>
		وحدة Node. ادمج Lighthouse في نظام التكامل المستمر (Continuous integration) الخاصّ بك.
	</li>
</ul>
<p>
	<strong>ملحوظة:</strong> تتطلّب كل واحدة من طرق العمل في Lighthouse وجود Google Chrome مثبَّت على جهازك.
</p>

<h3 id="-lighthouse-chrome">
	شغّل Lighthouse من أدوات تطوير Chrome
</h3>

<p>
	يشغّل Lighthouse لوحة Audits في أدوات تطوير Chrome. اتبع الخطوات التالية لتشغيل تقرير:
</p>

<ol>
<li>
		نزّل <a href="https://www.google.com/chrome/browser/desktop/" rel="external nofollow">Google Chrome للأجهزة المكتبية</a>.
	</li>
	<li>
		استخدم Google Chrome لتصفّح الصفحة التي تودّ تدقيقها. يمكنك تدقيق أي صفحة على الوِب.
	</li>
	<li>
		افتح أدوات التطوير DevTools في Chrome.
	</li>
	<li>
		انقر على اللسان <strong>Audits</strong>.<br><a class="ipsAttachLink ipsAttachLink_image" data-fileid="30118" href="https://academy.hsoub.com/uploads/monthly_2019_06/01_audits.png.97884e81d58586fdc90c557d83353a71.png" rel=""><img alt="01_audits.png" class="ipsImage ipsImage_thumbnailed" data-fileid="30118" data-unique="8tpcom3p0" src="https://academy.hsoub.com/uploads/monthly_2019_06/01_audits.thumb.png.98970b39738e5a31d5174adf4799768c.png"></a>
	</li>
	<li>
		يظهر في يسار الشاشة الإطار المعروض من الصفحة التي ستُدقَّق. تظهر في اليمين لوحة التدقيقات (Audits) التي يشغّلها Lighthouse.
	</li>
	<li>
		انقر على <strong>Perform an audit</strong>. تظهر أدوات التطوير قائمة بتصنيفات التدقيق. اتركها جميعا مُعلَّمة.
	</li>
	<li>
		انقر على <strong>Run audit</strong>. يعطيك Lighthouse بعد 60 إلى 90 ثانية تقريرًا عن الصفحة.<br><a class="ipsAttachLink ipsAttachLink_image" data-fileid="30119" href="https://academy.hsoub.com/uploads/monthly_2019_06/02_cdt-report.png.86bd42aa15da197fc6ee2733c2d41db0.png" rel=""><img alt="02_cdt-report.png" class="ipsImage ipsImage_thumbnailed" data-fileid="30119" data-unique="zvos4nayu" src="https://academy.hsoub.com/uploads/monthly_2019_06/02_cdt-report.thumb.png.0b6ac8232bc6d3c11c98e31337a17962.png"></a>
	</li>
</ol>
<h3 id="-node-">
	تثبيت سطر أوامر Node وتشغيله
</h3>

<p>
	اتبع الخطوات التالية لتثبيت وحدة Node:
</p>

<p>
	1- نزّل <a href="https://www.google.com/chrome/browser/desktop/" rel="external nofollow">Google Chrome للأجهزة المكتبية</a>.
</p>

<p>
	2- ثبّت الإصدار <a href="https://github.com/nodejs/LTS" rel="external nofollow">طويل الدعم</a> الحالي من <a href="https://nodejs.org/" rel="external nofollow">Node</a>.
</p>

<p>
	3- ثبّت Lighthouse. يشير الخيار <code>‎-g</code> إلى تثبيت الوحدة على مستوى النظام.
</p>

<pre class="ipsCode" id="ips_uid_2896_8">
npm install -g lighthouse
</pre>

<p>
	4- نفّذ الأمر التالي لتنفيذ تدقيق:
</p>

<pre class="ipsCode" id="ips_uid_2896_10">
lighthouse &lt;url&gt;</pre>

<p>
	5- لعرض خيارات التدقيق:
</p>

<pre class="ipsCode">
lighthouse --help</pre>

<h3 id="-node-">
	تشغيل وحدة Node برمجيا
</h3>

<p>
	راجع <a href="https://github.com/GoogleChrome/lighthouse/blob/master/docs/readme.md#using-programmatically" rel="external nofollow">استخدام هذا الرابط</a> لمثال على تشغيل Lighthouse برمجيًّا على صورة وحدة Node.
</p>

<h3 id="-lighthouse-extension-chrome">
	تشغيل Lighthouse عن طريقة إضافة Extension على Chrome
</h3>

<p>
	<strong>ملحوظة:</strong> يُفتَرض استخدام خطة سير عملا مبنية على أدوات المطوِّر في Chrome بدلا من هذه الإضافة، إلا إذا كان لديك سبب خاصّ. تُوفّر أدوات المطوّر في Chrome نفس الفوائد التي توفّرها الإضافة، علاوةً على كون الأدوات لا تحتاج لتثبيت.
</p>

<p>
	اتبع الخطوات التالية لتثبيت الإضافة:
</p>

<ol>
<li>
		نزّل <a href="https://www.google.com/chrome/browser/desktop/" rel="external nofollow">Google Chrome للأجهزة المكتبية</a>.
	</li>
	<li>
		ثبّت <a href="https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk" rel="external nofollow">إضافة Lighthouse</a> من مخزن إضافات Chrome.
	</li>
</ol>
<p>
	اتبع الخطوات التالية لتشغيل تدقيق:
</p>

<ol>
<li>
		استخدم Google Chrome لتصفّح الصفحة التي تودّ تدقيقها.
	</li>
	<li>
		انقر أيقونة Lighthouse. يُفتَرَض أن توجد الأيقونة بعد شريط العنوان في Chrome. إن لم تكن هناك، افتح القائمة الرئيسية في Chrome وانقر على الأيقونة في أعلى القائمة. تتمدّد قائمة Lighthouse بعد النقر على الأيقونة.<br><a class="ipsAttachLink ipsAttachLink_image" data-fileid="30120" href="https://academy.hsoub.com/uploads/monthly_2019_06/03_menu.png.b94a98d10de3611daf05b8998e8b8bc5.png" rel=""><img alt="03_menu.png" class="ipsImage ipsImage_thumbnailed" data-fileid="30120" data-unique="y1jqwwtnz" src="https://academy.hsoub.com/uploads/monthly_2019_06/03_menu.thumb.png.aa44e1591c087e79048003fe45fa8aab.png"></a>
	</li>
	<li>
		انقر على الزرّ <strong>Generate report</strong>. يدقّق Lighthouse الصفحة النشطة ثم يفتح لسانًا جديدًا يحوي تقريرًا عن نتائج تدقيق الصفحة.<br><a class="ipsAttachLink ipsAttachLink_image" data-fileid="30121" href="https://academy.hsoub.com/uploads/monthly_2019_06/04_report.png.e7bf359447a46a26712a7f4a92d718a4.png" rel=""><img alt="04_report.png" class="ipsImage ipsImage_thumbnailed" data-fileid="30121" data-unique="45r4ygrs5" src="https://academy.hsoub.com/uploads/monthly_2019_06/04_report.thumb.png.aed09f65544bd575743391137a5cd67d.png"></a>
	</li>
</ol>
<h2 id="-">
	شارك التقارير واعرضها على الشبكة
</h2>

<p>
	استخدم <a href="https://googlechrome.github.io/lighthouse/viewer/" rel="external nofollow">Lighthouse Viewer</a> (عارض Lighthouse) لعرض التقارير ومشاركتها على الشبكة.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="30122" href="https://academy.hsoub.com/uploads/monthly_2019_06/05_viewer.png.f01c5bbc5b89f4d91260a518e7d7991f.png" rel=""><img alt="05_viewer.png" class="ipsImage ipsImage_thumbnailed" data-fileid="30122" data-unique="n0qft2rzt" src="https://academy.hsoub.com/uploads/monthly_2019_06/05_viewer.thumb.png.da4ba248fc6ad25601c2f7616fb36c4a.png"></a>
</p>

<h3 id="-json">
	شارك التقارير بصيغة JSON
</h3>

<p>
	يحتاج Lighthouse Viewer إلى مُخرج بصيغة JSON من تقرير Lighthouse. تشرح الخطوات أدناه كيفية الحصول على مُخرج بصيغة JSON، حسب طريقة العمل التي اخترتها.
</p>

<ul>
<li>
		بالنسبة لأدوات التطوير: انقر على تنزيل التقرير (السهم المتّجه إلى الأسفل).
	</li>
	<li>
		<p>
			سطر الأوامر:
		</p>

		<pre class="ipsCode" id="ips_uid_2896_12">
      lighthouse --output json --output-path &lt;path/for/output.json&gt;
</pre>

		<p>
			 
		</p>
	</li>
	<li>
		<p>
			إضافة Chrome: انقر على زرّ التصدير <strong>Export</strong> ثم <strong>Save as JSON</strong>.
		</p>
	</li>
</ul>
<p>
	لمعاينة بيانات التقرير:
</p>

<ol>
<li>
		افتح Lighthouse Viewer في متصفّح Chrome.
	</li>
	<li>
		اسحب ملف JSON إلى العارض ثم أفلته، أو انقر في أي مكان في العارض لفتح متصفّح الملفّات لديك واختيار الملفّ.
	</li>
</ol>
<h3 id="-github-gists">
	مشاركة التقارير عبر GitHub Gists
</h3>

<p>
	إن لم تكن ترغب في تمرير تقاريرك يدويّا بصيغة ملفات JSON فيمكنك مشاركتها بسريّة عبر خدمة GitHub Gists. أحد فوائد الخدمة هو الحصول على تحكّم مجاني في الإصدارات Version control.
</p>

<p>
	اتبع الخطوات التالية لتصدير التقارير إلى GitHub Gists عبر إضافة Lighthouse على Chrome:
</p>

<ol>
<li>
		انقر على <strong>Export</strong> ثم <strong>Open In Viewer</strong>. يُفتَح التقرير في العارض المتوفّر على الرابط <a href="https://googlechrome.github.io/lighthouse/viewer/" rel="external nofollow">https://googlechrome.github.io/lighthouse/viewer/</a>.
	</li>
	<li>
		انقر على المشاركة <strong>Share</strong> في العارض. ستطلُب منك نافذة منبثقة في المرة الأولى السماح بالوصول إلى بياناتك الأساسية على GitHub، وصلاحية القراءة والكتابة على GitHub Gists.
	</li>
</ol>
<p>
	أنشئ Gist يدويًّا ثم انسخ التقرير بصيغة JSON وألصقه، إن أردت تصدير التقرير إلى GitHub Gists من سطر الأوامر. يجب أن ينتهي اسم Gist الذي يحوي مُخرَج JSON باللاحقة <code>lighthouse.report.json</code>. راجع هذا الرابط لمثال على كيفية توليد مُخرَج JSON من سطر الأوامر.
</p>

<p>
	اختر إحدى الطريقتيْن التاليّتين لعرض تقرير محفوظ على GitHub Gists: .
</p>

<ul>
<li>
		أضف <code>‎?gist=&lt;ID&gt;‎</code> إلى رابط العارض، حيثُ <code>ID</code> هو معرّف Gist: <code><a href="https://googlechrome.github.io/lighthouse/viewer/?gist=%3CID%3E" rel="external nofollow">https://googlechrome.github.io/lighthouse/viewer/?gist=&lt;ID&gt;</a></code>‎
	</li>
	<li>
		افتح <a href="https://googlechrome.github.io/lighthouse/viewer/" rel="external nofollow">العارض</a> وألصق فيه رابط Gist
	</li>
</ul>
<h2 id="-lighthouse">
	المساهمة في Lighthouse
</h2>

<p>
	Lighthouse مفتوح المصدر، و<a href="https://github.com/GoogleChrome/lighthouse/blob/master/CONTRIBUTING.md" rel="external nofollow">يرحّب مطوّروه بالمساهمة فيه</a>. تحقّق من متتبّع المشاكل Issues tracker في المستودع للعثور على <a href="https://github.com/GoogleChrome/lighthouse/issues" rel="external nofollow">علل</a> (Bugs) يمكنك إصلاحها، أو تدقيقات يمكنك إنشاؤها أو تحسينها. يعدّ متتبّع المشاكل مكانا جيّدا للنقاش حول قياسات التدقيق أو أفكار لتدقيقات جديدة أو أي أمر آخر له علاقة بأداة Lighthouse.
</p>

<p>
	ترجمة - بتصرّف - للمقال <a href="https://developers.google.com/web/tools/lighthouse/" rel="external nofollow">Lighthouse</a> من موقع مطوّري Chrome.
</p>
]]></description><guid isPermaLink="false">691</guid><pubDate>Sun, 16 Jun 2019 12:10:27 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644;&#x643; &#x627;&#x644;&#x634;&#x627;&#x645;&#x644; &#x625;&#x644;&#x649; &#x623;&#x62F;&#x627;&#x629; &#x627;&#x644;&#x628;&#x646;&#x627;&#x621; Gulp</title><link>https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%A3%D8%AF%D8%A7%D8%A9-%D8%A7%D9%84%D8%A8%D9%86%D8%A7%D8%A1-gulp-r663/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_04/Gulp.png.bda45a939bb8043e09643bf4ce2fb1b1.png" /></p>

<p>
	تتوفر عدِّة «أدوات بناء» (build tools) تعمل على تسهيل عملية تطوير مواقع الويب وأتمتة المهام الروتينية مثل «تصغير» (minify) ملفات JavaScript و HTML و CSS والصور، وتحويل ملفات LESS و SASS إلى CSS، والتحقق مباشرةً من صحة البنية اللغوية لملفات JavaScript والكثير من الأمور التي ستغيّر من طريقة عملك وتجعلها أكثر سرعةً وكفاءة.
</p>

<p>
	سنشرح في درسنا هذا إحدى أدوات البناء المشهورة وهي الأداة Gulp بالإضافة إلى أساسيات استخدامها، شرحًا مدعمَّا بالأمثلة العملية.
</p>

<p>
	<strong>ملاحظة مهمة</strong>: هذا الدليل كتب من أجل الإصدار 3 من Gulp وهنالك بعض الاختلافات والتغييرات الجوهرية في الإصدار 4. لذلك، إن كنت تستعمل الإصدار 4، فهذا الدليل ليس لك لأنه هنالك بعض الدوال والواجهات البرمجية التي لن تعمل مع ذلك الإصدار.
</p>

<h2 id="gulp-1">
	ما هي أداة البناة Gulp؟
</h2>

<p>
	أدوات البناء هو أمر حديث العهد ولم ينتشر إلا منذ بضعة سنوات. كانت ملفات ‎.sh التي تكتب بلغة Bash أحد أشهر أدوات البناء غير المباشرة وغير المخصصة المستعملة آنذاك لكتابة التعليمات وأتمتة بعض المهام الروتينية المحدودة مثل مراقبة الملفات وتحديثها. هذه الملفات تعمل مع الصدفة shell التي تأتي مدمجة مع أنظمة التشغيل.
</p>

<p>
	انتشرت أدوات بناء أخرى مثل <a href="https://ant.apache.org/" rel="external nofollow">Ant</a> و <a href="https://gradle.org/" rel="external nofollow">Gradle</a> ولكنهما كانتا ضمن عالم جافا وتحتاجان إلى استعمال لغة XML لضبطهما وهي اللغة التي لا يحبها مطوري الويب عدا عن تعلم لغة جديدة لا يألفونها. اللغة التي يحبها مطورو الويب هي جافاسكربت وهنا جاءت أداتا البناء <a href="https://gulpjs.com/" rel="external nofollow">Gulp</a> و <a href="https://gruntjs.com/" rel="external nofollow">Grunt</a> لسد هذه الفجوة.
</p>

<p>
	تتفوق أداة البناء Gulp على منافستها Grunt بأنها أسرع بكثير لأنها تنفذ المهام على التوازي (على عكس Grunt) كما أنها تمرر الملفات المفتوحة عبر مجاري Streams داخلية. أضف إلى ذلك أن اللغة المستعملة في ضبط مهام Gulp هي جافاسكريبت بالتأكيد وهي اللغة التي يحبها مطورو الويب كثيرًا.
</p>

<h2 id="">
	المتطلبات المسبقة
</h2>

<p>
	سيجري العمل على نظام التشغيل أوبنتو 18.04 ويجب أن تكون قد ثبَّت Node.js و npm مسبقًا. إن لم تكن Node.js مثبتةً لديك، فابدأ بتثبيتها هي ومدير <a href="https://en.wikipedia.org/wiki/Npm_(software)" rel="external nofollow">الحزم npm عبر</a> الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_5720_59">
sudo apt update
sudo apt install nodejs</pre>

<p>
	للتحقق من عملية التثبيت (وللتأكد من الإصدار المثبت مسبقًا لديك)، نفذ الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_5720_30">
nodejs --version
</pre>

<p>
	يجب أن ترى ناتجًا شبيهًا بالناتج التالي:
</p>

<pre class="ipsCode" id="ips_uid_5720_32">
v8.10.0
</pre>

<p>
	ولتكون قادرًا على تنزيل وتثبيت حزم npm، تحتاج إلى تنزيل npm (مدير حزم Node.js) إن لم يكن مثبَّتًا لديك:
</p>

<pre class="ipsCode" id="ips_uid_5720_34">
sudo apt install npm
</pre>

<p>
	تحقق من عملية التثبيت (أو الإصدار المثبت مسبقًا) عبر الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_5720_38">
npm --version
</pre>

<p>
	يجب أن ترى ناتجًا شبيهًا بالناتج التالي:
</p>

<pre class="ipsCode" id="ips_uid_5720_40">
3.5.2
</pre>

<p>
	أنت الآن جاهز لإكمال هذا الدليل!
</p>

<h2 id="gulp-2">
	تثبيت Gulp
</h2>

<p>
	يمكن تثبيت Gulp عبر مدير الحزم npm الذي تحدثنا عنه منذ قليل، بشكل سهلٌ للغاية فكل ما عليك فعله هو تنفيذ الأمر الآتي في سطر الأوامر لتثبيت Gulp 3 لعموم النظام:
</p>

<pre class="ipsCode" id="ips_uid_1157_6">
npm install gulp@3.9.0 </pre>

<p>
	ثم عليك تهيئة مجلد المشروع الذي ستعمل عليه. نفِّذ الأمر الآتي في مجلد المشروع:
</p>

<pre class="ipsCode" id="ips_uid_5720_61">
npm init
</pre>

<p>
	عليك الآن تثبيت Gulp في المشروع وإضافته إلى الاعتماديات (أي <code>devDependencies</code>):
</p>

<pre class="ipsCode" id="ips_uid_5720_63">
npm install --save-dev gulp
</pre>

<p>
	أصبح Gulp مثبتًا في مشروعك وجاهزًا للاستخدام.
</p>

<h2 id="-1">
	البنية الهيكلية للمشروع الذي سنعمل عليه
</h2>

<p>
	مرونة Gulp تسمح لنا باستخدامه بغض النظر عن بنية المجلدات التابعة للمشروع، كل ما يلزمك هو فهمٌ صحيحٌ كاملٌ لآلية عمله مما يسمح لك بتعديله لتلبية احتياجاتك. سنعتمد في مقالتنا البنية الآتية للمجلدات:
</p>

<pre class="ipsCode" id="ips_uid_5720_65">
  |- app/
      |- css/
      |- fonts/
      |- images/ 
      |- index.html
      |- js/ 
      |- scss/
  |- dist/
  |- gulpfile.js
  |- node_modules/
  |- package.json
</pre>

<p>
	هذه بنيةٌ بسيطة نستعمل فيها مجلد <code>app</code> لاحتواء ملفات التطوير، بينما المجلد <code>dist</code> (اختصار للكلمة «distribution») سيحتوي على الملفات الإنتاجية.
</p>

<h2 id="gulp-3">
	كتابة أول مهمة من مهام Gulp
</h2>

<p>
	عندما نُشغِّل Gulp من سطر الأوامر، فسيبحث عن وجود الملف <code>gulpfile.js</code> في مجلد المشروع. سيُخبِر هذا الملف Gulp ما هي الإضافات التي يجب تحميلها وما هي المهام التي يجب القيام بها. علينا إذًا إنشاء الملف <code>gulpfile.js</code> وتضمين gulp في بدايته كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_67" style="">
<span class="kwd">var</span><span class="pln"> gulp </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp'</span><span class="pun">);</span></pre>

<p>
	عبارة require السابقة ستخبر Node أن تبحث في مجلد <code>node_modules</code> عن حزمة باسم <code>gulp</code>، وعند العثور عليها فستُسنَد محتوياتها إلى المتغير <code>gulp</code>. يمكننا الآن البدء بكتابة «مهمّة Gulp» (أي Gulp task) بالاستفادة من المتغير <code>gulp</code>. البنية الأساسية لمهمّة Gulp هي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_69" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'task-name'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// سنضع الشيفرات هنا</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	<code>task-name</code> تشير إلى اسم المهمّة، والتي ستُستعمَل في أي مكانٍ تريد تشغيل هذه المهمّة فيه. نستطيع تشغيل هذه المهمة بتمرير اسمها كوسيط للأمر <code>gulp</code> في سطر الأوامر (أي تنفيذ <code>gulp task-name</code>). لنجرِّب ما سبق بإنشائنا للمهمّة <code>hello</code> في ملف <code>gulpfile.js</code> السابق (الذي يحتوي على عبارة <code>require</code>) والتي ستطبع الجملة <code>Hello World</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_71" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'hello'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Hello World'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يمكننا تشغيل هذه المهمة بتنفيذ الأمر <code>gulp hello</code> في سطر الأوامر، لا تنسَ الانتقال إلى مجلد المشروع (عبر الأمر <code>cd</code> في لينكس أو ماك، أو <code>dir</code> في ويندوز) قبل تنفيذ الأمر. مخرجات الأمر السابق هي:
</p>

<pre class="ipsCode" id="ips_uid_5720_73">
user@linuxbox:~/gulp-test$ gulp hello
[18:34:41] Using gulpfile ~/gulp-test/gulpfile.js
[18:34:41] Starting 'hello'...
Hello World
[18:34:41] Finished 'hello' after 127 μs
</pre>

<p>
	حسنًا، لا تكون مهام Gulp بهذه البساطة، حيث تحتوي عادةً على دالتين تابعتين للكائن <code>gulp</code> بالإضافة إلى استخدام إضافة (plugin) أو أكثر من إضافات Gulp. هذا مثالٌ عن البنية العامة لمهمّات Gulp:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_75" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'task-name'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">//الحصول على الملفات التي يجب إجراء عمليات عليها</span><span class="pln">
  </span><span class="com">// gulp.src باستخدام الدالة</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'source-files'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">aGulpPlugin</span><span class="pun">())</span><span class="pln"> </span><span class="com">// ومن ثم تمريرها إلى إضافة</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'destination'</span><span class="pun">))</span><span class="pln"> </span><span class="com">// وإخراج الملف إلى المجلد الهدف</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	كما هو واضح، تتطلب المهام المفيدة في gulp دالتين هما <code>gulp.src</code> و <code>gulp.dest</code>. الدالة <code>gulp.src</code> تخبر Gulp ما هي الملفات التي يجب تطبيق المهمة عليها، بينما الدالة <code>gulp.dest</code> تخبر Gulp أين يجب إخراج الملفات بعد تنفيذ المهمّة.
</p>

<p>
	يَستخدم Gulp المجاري (streams) التي توفرها node.js، وهذا يسمح بتمرير البيانات التي ستُعالَج عبر الأنابيب (pipes) وهذا ما تفعله الدالة <code>‎.pipe()‎</code>؛ لشرحٍ تفصيليٍ عن المجاري في node.js، فأحيلك إلى <a href="https://github.com/substack/stream-handbook" rel="external nofollow">هذه المقالة</a>.
</p>

<p>
	سنشرح كيفية الاستفادة من Gulp عبر استعماله لتحويل ملفات Sass إلى ملفات CSS.
</p>

<h2 id="sasscssgulp">
	تحويل ملفات Sass إلى CSS عبر Gulp
</h2>

<p>
	نستطيع استخدام إضافة باسم <a href="https://www.npmjs.com/package/gulp-sass" rel="external nofollow">gulp-sass</a> لتحويل ملفات Sass إلى CSS. عليك تثبيت الإضافة <code>gulp-sass</code> في مشروعك باستخدام الأمر <code>npm install</code> كما فعلنا سابقًا مع <code>gulp</code>.
</p>

<p>
	يفضل أيضًا استخدام الخيار <code>‎--save-dev</code> لكي تُضاف الحزمة gulp-sass إلى <code>devDependencies</code> في ملف <code>package.json</code> وهذا يسهل نسخ الملف إلى مشروع آخر وتثبيت نفس الاعتماديات (عبر الأمر <code>npm install</code> فقط):
</p>

<pre class="ipsCode" id="ips_uid_5720_77">
npm install gulp-sass –save-dev
</pre>

<p>
	علينا الآن تضمين الحزمة gulp-sass عبر <code>require</code> من مجلد <code>node_modules</code> كما فعلنا أول مرة مع <code>gulp</code> كي نتمكن من استخدام الإضافة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_79" style="">
<span class="kwd">var</span><span class="pln"> gulp </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp'</span><span class="pun">);</span><span class="pln">
</span><span class="com">// gulp-sass تضمين إضافة</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> sass </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-sass'</span><span class="pun">);</span></pre>

<p>
	يمكننا استخدام gulp-sass بوضع الدالة <code>sass()‎</code> بدلًا من <code>aGulpPlugin()‎</code> في المثال السابق. ولمّا كان الغرض من المهمّة هو تحويل ملفات Sass إلى CSS فلنسمِّها <code>sass</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_81" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'sass'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'source-files'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">sass</span><span class="pun">())</span><span class="pln"> </span><span class="com">// gulp-sass استخدام إضافة</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'destination'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	علينا توفير ملفات مصدرية بصيغة sass -ومجلد لإخراج الناتج فيه- إلى المهمّة <code>sass</code>، لنبدأ بإنشاء الملف <code>styles.scss</code> في مجلد <code>app/scss</code>، ومن ثم سنضع مسار هذا الملف في الدالة <code>gulp.src</code> في مهمّة <code>sass</code>. ونريد أيضًا إخراج ملف <code>styles.css</code> النهائي إلى مجلد <code>app/css</code> الذي سيكون هو مجلد الوجهة (destination) لدالة <code>gulp.dest</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_83" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'sass'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/scss/styles.scss'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">sass</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'app/css'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	سنختبر المهمّة <code>sass</code> الآن للتأكد من عملها عملًا صحيحًا، لكن قبل ذلك علينا استخدام دالة من دوال Sass ضمن ملف <code>styles.scss</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_85" style="">
<span class="com">// styles.scss</span><span class="pln">
</span><span class="pun">.</span><span class="pln">testing </span><span class="pun">{</span><span class="pln">
  width</span><span class="pun">:</span><span class="pln"> percentage</span><span class="pun">(</span><span class="lit">5</span><span class="pun">/</span><span class="lit">7</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا نفَّذتَ الأمر <code>gulp sass</code> في سطر الأوامر، فيجب أن يُنشَأ الملف <code>styles.css</code> في مجلد <code>app/css</code>، مع تبديل الدالة <code>percentage(5/7)‎</code> وتحويلها إلى <code>71.42857%‎</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_87" style="">
<span class="com">/* styles.css */</span><span class="pln">
</span><span class="pun">.</span><span class="pln">testing </span><span class="pun">{</span><span class="pln">
  width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">71.42857</span><span class="pun">%;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	تحققنا أنَّ المهمّة <code>sass</code> تعمل بشكلٍ سليم. أحيانًا نحتاج إلى بناء أكثر من ملف <code>‎.scss</code> وتحويلها إلى ملفات CSS في نفس الوقت، وسنحتاج حينها إلى استخدام «محارف التحديد» (Globs).
</p>

<h2 id="node">
	محارف التحديد في Node
</h2>

<p>
	تسمح لك محارف التحديد بتمرير أكثر من ملف إلى الدالة <code>gulp.src</code>، وهي شبيهة بالتعابير النمطية (regular expressions) لكنها تُستعمَل خصيصًا لمسارات الملفات.
</p>

<p>
	عند استخدامك لمحرف تحديد (glob) فسيتحقق جهازك من أسماء الملفات والمسارات المُحدَّدة بالنمط المستخدم، فإن تمت مطابقة النمط فسيُضاف الملف إلى الدالة <code>gulp.src</code>.
</p>

<p>
	أغلبية الأنماط التي نستعملها مع Gulp تنضوي تحت لواء الأنماط الآتية:
</p>

<ol>
<li>
		النمط <code>‎*.scss</code>: رمز النجمة <code>*</code> هو محرفٌ خاصٌ يُطابِق أيّة ملف في المجلد المعيّن. وفي مثالنا ستُطابَق جميع الملفات التي تنتهي باللاحقة <code>‎.scss</code> في المجلد الرئيسي للمشروع.
	</li>
	<li>
		النمط <code>‎**/*.scss</code>: هذه حالةٌ أعم من المثال السابق، حيث ستتم مطابقة أيّة ملفات تنتهي باللاحقة <code>‎.scss</code> في المجلد الرئيسي للمشروع وفي جميع المجلدات الفرعية الموجودة فيه.
	</li>
	<li>
		النمط <code>‎!not-me.scss</code>: الرمز <code>!</code> يعني أنَّ على Gulp استثناء هذا النمط من الملفات المُحدَّدة، وهذا مفيدٌ إن شئتَ أن تستثني ملفًا من التحويل؛ وفي مثالنا سنستثني الملف <code>not-me.scss</code>.
	</li>
	<li>
		النمط <code>‎*.+(scss|sass)</code>: إشارة الزائد <code>+</code> والأقواس <code>()‎</code> ستسمح لأداة Gulp بمطابقة عدِّة أنماط معًا، والتي سيُفصَل بينها بمحرف الخط العمودي <code>|</code>. وفي مثالنا سيُطابِق Gulp جميع الملفات التي تنتهي باللاحقة <code>‎.scss</code> أو <code>‎.sass</code> في المجلد الرئيسي للمشروع.
	</li>
</ol>
<p>
	بعد تعلمنا لمحارف التحديد، أصبح بإمكاننا وضع التعبير <code>app/scss/**/*.scss</code> بدلًا من <code>app/scss/styles.scss</code>، وبهذا ستُطابَق جميع الملفات التي لها اللاحقة <code>‎.scss</code> في المجلد <code>app/scss</code> أو أيّ مجلدٍ فرعيٍ موجودٍ داخله.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_89" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'sass'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// scss الحصول على جميع الملفات التي تنتهي باللاحقة</span><span class="pln">
  </span><span class="com">// app/scss والموجودة في المجلد</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">sass</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'app/css'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	سيُضمَّن أيّ ملف Sass موجود في مجلد <code>app/scss</code> تلقائيًا في مهمّة <code>sass</code> المُعدَّلة. فلو أضفتَ ملف <code>print.scss</code> إلى المشروع، فستلاحظ توليد الملف <code>print.css</code> في مجلد <code>app/css</code> تلقائيًا. حسنًا، تمكّنا من تحويل جميع ملفات Sass إلى ملفات CSS بأمرٍ وحيد، لكن السؤال الآن هو: ما الفائدة من المهمّة التي أنشأناها إن كنا سنحتاج إلى تطبيق الأمر <code>gulp sass</code> يدويًا في كل مرة نرغب فيها بتحويل ملفات Sass إلى CSS؟ لحسن الحظ، يمكننا أن نخبر Gulp أن يُشغِّل المهمّة <code>sass</code> تلقائيًا في كل مرة يُحفَظ فيها أحد تلك الملفات، وهذا ما ندعوه «المراقبة» (watching).
</p>

<h2 id="sass">
	مراقبة التغييرات في ملفات Sass
</h2>

<p>
	يوفِّر لنا Gulp الدالة <code>watch</code> لمعرفة إن حُفِظَ أحد الملفات. الشكل العام لدالة <code>watch</code> هو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_91" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'files-to-watch'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'to'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'run'</span><span class="pun">]);</span><span class="pln"> </span></pre>

<p>
	إذا أردنا مراقبة جميع ملفات Sass وتشغيل المهمّة <code>sass</code> عندما يحفظ أحد تلك الملفات، فعلينا أن نضع <code>app/scss/**/*.scss</code> بدلًا من <code>files-to-watch</code> ونضع <code>['sass']</code> بدلًا من <code>['tasks', 'to', 'run']</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_93" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'sass'</span><span class="pun">]);</span><span class="pln"> </span></pre>

<p>
	وفي أغلبية الأوقات سنحتاج إلى مراقبة أكثر من نوع من الملفات في آنٍ واحد، ويمكننا إنشاء مجموعة من عمليات المراقبة مع بعضها ضمن مهمّة باسم <code>watch</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_95" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'watch'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'sass'</span><span class="pun">]);</span><span class="pln"> 
  </span><span class="com">// عمليات المراقبة الأخرى</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	إذا جرّبتَ تنفيذ الأمر <code>gulp watch</code> الآن، فسترى أنَّ Gulp قد بدأ مراقبة الملفات فوريًا.
</p>

<pre class="ipsCode" id="ips_uid_5720_97">
user@linuxbox:~/gulp-test$ gulp watch
[21:10:00] Using gulpfile ~/gulp-test/gulpfile.js
[21:10:00] Starting 'watch'...
[21:10:00] Finished 'watch' after 12 ms
</pre>

<p>
	وأنَّ Gulp سيُنفِّذ المهمّة <code>sass</code> عندما تحفظ أحد ملفات <code>‎.scss</code>، جرِّب الآن فتح الملف <code>styles.scss</code> السابق وإضافة أيّ شيء إليه وحفظه، ثم انظر إلى ناتج Gulp:
</p>

<pre class="ipsCode" id="ips_uid_5720_99">
abd@linuxbox:~/gulp-test$ gulp watch
[21:10:00] Using gulpfile ~/gulp-test/gulpfile.js
[21:10:00] Starting 'watch'...
[21:10:00] Finished 'watch' after 12 ms
[21:12:03] Starting 'sass'...
[21:12:03] Finished 'sass' after 69 ms
</pre>

<p>
	ما رأيك أن نخطو خطوةً إلى الأمام ونجعل Gulp يُعيد تحميل الصفحة عندما نحفظ أحد ملفات <code>‎.scss</code> لكي يظهر تأثير تغيير الصفحة مباشرةً على المتصفح، وذلك بالاستعانة بأداة <a href="http://www.browsersync.io/" rel="external nofollow">Browser Sync</a>.
</p>

<h2 id="browsersync">
	تحديث الصفحة آنيًا باستخدام Browser Sync
</h2>

<p>
	يُسهِّل <a href="https://www.browsersync.io/docs/gulp" rel="external nofollow">Browser Sync</a> من تطوير الويب بإنشاء خادوم ويب الذي يساعدنا على تحديث الصفحات آنيًا عند تغييرها. وله ميزاتٌ أخرى، مثل مزامنة الأحداث بين أكثر من جهاز. لنبدأ أولًا بتثبيت الأداة Browser Sync كالمعتاد:
</p>

<pre class="ipsCode" id="ips_uid_5720_101">
npm install browser-sync –save-dev
</pre>

<p>
	علينا بعدئذٍ أن نُضمِّن Browser Sync عبر التعليمة <code>require</code>:
</p>

<pre class="ipsCode" id="ips_uid_5720_103">
var browserSync = require('browser-sync').create();
</pre>

<p>
	سنحتاج إلى إنشاء مهمّة باسم <code>browserSync</code> للسماح لأداة Gulp بتشغيل خادوم ويب باستخدام Browser Sync، ولأننا سنُنشِئ خادوم ويب، فعلينا أن نُحدِّد للخادوم ما هو المجلد الرئيسي للموقع، والذي هو في حالتنا المجلد <code>app</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_105" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'browserSync'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  browserSync</span><span class="pun">.</span><span class="pln">init</span><span class="pun">({</span><span class="pln">
    server</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      baseDir</span><span class="pun">:</span><span class="pln"> </span><span class="str">'app'</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
  </span><span class="pun">})</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	علينا أيضًا تغيير المهمّة <code>sass</code> قليلًا لكي يتمكن Browser Sync من تحديث أنماط CSS في المتصفح عندما تُشغَّل المهمّة <code>sass</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_109" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'sass'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">)</span><span class="pln"> 
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">sass</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'app/css'</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">browserSync</span><span class="pun">.</span><span class="pln">reload</span><span class="pun">({</span><span class="pln">
      stream</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
    </span><span class="pun">}))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	انتهينا الآن من ضبط الأداة Browser Sync، لكن علينا تشغيل المهمّتَين <code>watch</code> و <code>browserSync</code> في نفس الوقت لكي تُحدَّث الصفحة آنيًا.
</p>

<p>
	من غير المقبول فتح نافذَتي سطر أوامر وتشغيل <code>gulp browserSync</code> في إحداها و <code>gulp watch</code> في الأخرى، لذا لنجعل Gulp يشغِّلهما معًا بإخبار المهمّة <code>watch</code> أنَّه يجب إكمال المهمّة <code>browserSync</code> قبل السماح بتنفيذ <code>watch</code>.
</p>

<p>
	يمكننا فعل ذلك بتمرير وسيطٍ ثانٍ إلى المهمّة <code>watch</code>. الشكل العام هو:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_111" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'watch'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'array'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'of'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tasks'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'to'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'complete'</span><span class="pun">,</span><span class="str">'before'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'watch'</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln">
  </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	وفي حالتنا هذه سنضيف المهمّة <code>browserSync</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_113" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'watch'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'browserSync'</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln">
  gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'sass'</span><span class="pun">]);</span><span class="pln"> 
  </span><span class="com">// عمليات المراقبة الأخرى</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	علينا أيضًا أن نتأكد أنَّ المهمّة <code>sass</code> ستعمل قبل <code>watch</code> لكي يتم تحويل أيّة ملفات sass حُفِظَت قبل تشغيل Gulp إلى ملفات CSS.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_115" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'watch'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'browserSync'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'sass'</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln">
  gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'sass'</span><span class="pun">]);</span><span class="pln"> 
  </span><span class="com">// عمليات المراقبة الأخرى</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إذا شغَّلتَ <code>gulp watch</code> في سطر الأوامر، فسيُشغِّل Gulp المهمّتين <code>sass</code> و <code>browserSync</code> ثم بعد إكمالهما ستُشغَّل المهمّة <code>watch</code>. ستجد في الناتج رابط URL شبيه بالرابط الآتي <a href="http://localhost:3000" rel="external nofollow">http://localhost:3000</a> الذي إذا فتحته في نافذة المتصفح، فسترى صفحة <code>app/index.html</code> التي يجب أن يكون محتواها شبيهًا بما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5720_57" style="">
<span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;head&gt;&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"css/styles.css"</span><span class="tag">&gt;&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	شغِّل الآن المتصفح وادخل إلى الرابط السابق وستعرض أمامك صفحة فارغة، ولتجربة التحديث الآني للصفحة، فافتح ملف styles.scss وأضف لونًا للخلفية (مثلًا: <code>body {background-color: red;}</code> واحفظ الملف وستجد أنَّ الصفحة قد حُدِّثَت تلقائيًا!
</p>

<p>
	ما رأيك الآن أن نضيف قليلًا على المهمّة السابقة ونراقب تغيير ملفات HTML أو JavaScript (بالإضافة إلى ملفات <code>‎.sass</code>) ومن ثم إعادة تحميل الصفحة حينها؟
</p>

<p>
	يمكننا فعل ذلك بإضافة عمليتَي مراقبة، واستدعاء الدالة <code>browserSync.reload</code> عند حفظ الملف:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_55" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'watch'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'browserSync'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'sass'</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln">
  gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/scss/**/*.scss'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'sass'</span><span class="pun">]);</span><span class="pln"> 

  </span><span class="com">// تحديث الصفحة عند حفظ هذه الملفات</span><span class="pln">
  gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/*.html'</span><span class="pun">,</span><span class="pln"> browserSync</span><span class="pun">.</span><span class="pln">reload</span><span class="pun">);</span><span class="pln"> 
  gulp</span><span class="pun">.</span><span class="pln">watch</span><span class="pun">(</span><span class="str">'app/js/**/*.js'</span><span class="pun">,</span><span class="pln"> browserSync</span><span class="pun">.</span><span class="pln">reload</span><span class="pun">);</span><span class="pln"> 
</span><span class="pun">});</span></pre>

<p>
	حتى الآن قمنا بثلاثة أمور:
</p>

<ol>
<li>
		تشغيل خادوم ويب للتطوير
	</li>
	<li>
		تحويل ملفات Sass إلى CSS
	</li>
	<li>
		إعادة تحميل الصفحة في المتصفح عند حفظ الملفات
	</li>
</ol>
<p>
	سنشرح في القسم الآتي كيفية تحسين الملفات الملحقة بصفحات الويب، وسنبدأ بتحسين ملفات CSS و JavaScript.
</p>

<h2 id="cssjavascript">
	تحسين ملفات CSS و JavaScript
</h2>

<p>
	يُجري المطورون مهمّتَين عندما يحاولون تحسين ملفات CSS و JavaScript: تصغير الملفات وجمعها في ملفٍ واحد. إحدى المشاكل التي يواجهها المطورون عند أتمتة هذه العملية هي الصعوبة في جمع السكربتات بترتيبٍ صحيح. لنقل أننا أضفنا 3 وسوم script في صفحة <code>index.html</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5720_118" style="">
<span class="tag">&lt;body&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/lib/a-library.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/lib/another-library.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/main.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span></pre>

<p>
	هذه السكربتات موجودة في مجلدين مختلفين، ومن الصعب جمعها باستخدام الإضافات التقليدية مثل <a href="https://www.npmjs.com/package/gulp-concat" rel="external nofollow">gulp-concatenate</a>؛ لكن لحسن الحظ، تأتي إضافة <a href="https://www.npmjs.com/package/gulp-useref" rel="external nofollow">gulp-useref</a> لتحل لنا هذه الإشكالية.
</p>

<p>
	تجمع إضافة gulp-useref أيّ عدد من ملفات CSS أو JavaScript إلى ملفٍ وحيد بالبحث عن تعليق يبدأ بالتعبير <code>‎&lt;!--build:‎</code> وينتهي بالتعبير <code>&lt;‎!--endbuild--‎&gt;</code> الشكل العام له هو:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5720_123" style="">
<span class="com">&lt;!-- build:&lt;type&gt; &lt;path&gt; --&gt;</span><span class="pln">
... HTML Markup, list of script / link tags.
</span><span class="com">&lt;!-- endbuild --&gt;</span></pre>

<p>
	النوع <code>&lt;type&gt;</code> يمكن أن يكون إما <code>js</code> أو <code>css</code> أو <code>remove</code>. من الأفضل تحديد نوع <code>type</code> للملفات التي تحاول جمعها؛ وإذا ضَبطتَ <code>type</code> إلى <code>remove</code> فسيَحذف Gulp الشيفرةَ المُحدَّدةَ ولن يولِّد ملفًا. أما <code>&lt;path&gt;</code> فيشير إلى مسار الملف الذي سيولّد.
</p>

<p>
	إذا أردتَ أن يكون ملف JavaScript المولَّد في مجلد <code>js</code> باسم <code>main.min.js</code> فستبدو الشيفرة كالآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4527_6" style="">
<span class="com">&lt;!--build:js js/main.min.js --&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/lib/a-library.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/lib/another-library.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/main.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
</span><span class="com">&lt;!-- endbuild --&gt;</span></pre>

<p>
	لنضبط الآن إضافة gulp-useref في ملف <code>gulpfile.js</code>. علينا أولًا تثبيت الإضافة ثم تضمينها في الملف. نفِّذ الأمر الآتي للتثبيت:
</p>

<pre class="ipsCode" id="ips_uid_5720_125">
npm install gulp-useref –save-dev
</pre>

<p>
	أضف السطر الآتي إلى ملف <code>gulpfile.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4527_8" style="">
<span class="kwd">var</span><span class="pln"> useref </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-useref'</span><span class="pun">);</span></pre>

<p>
	تهيئة المهمّة <code>useref</code> شبيهة بتهيئة المهام الأخرى التي أنجزناها من قبل. هذه هي الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_129" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'useref'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/*.html'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">useref</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'dist'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	إذا شغّلتَ مهمّة <code>useref</code> الآن فسيأخذ Gulp ملفات JavaScript المُحدَّدة وسيجمعها في ملف <code>dist/js/main.min.js</code>.
</p>

<p>
	لكن الملف لم يُصغَّر (minified) إلى الآن، وعلينا استخدام إضافة <a href="https://www.npmjs.com/package/gulp-uglify" rel="external nofollow">gulp-uglify</a> لفعل ذلك. وسنحتاج أيضًا إلى إضافة تدعى <a href="https://github.com/robrich/gulp-if" rel="external nofollow">gulp-if</a> لكي نُصغّر ملفات JavaScript دونًا عن غيرها. تثبيت الإضافة:
</p>

<pre class="ipsCode" id="ips_uid_5720_131">
npm install gulp-uglify --save-dev 
</pre>

<p>
	الشيفرة التي سنضيفها إلى ملف <code>gulpfile.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_133" style="">
<span class="kwd">var</span><span class="pln"> uglify </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-uglify'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> gulpIf </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-if'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'useref'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/*.html'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">useref</span><span class="pun">())</span><span class="pln">
    </span><span class="com">// JavaScript التصغير إذا كان الملف</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulpIf</span><span class="pun">(</span><span class="str">'*.js'</span><span class="pun">,</span><span class="pln"> uglify</span><span class="pun">()))</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'dist'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يجب أن يولِّدَ Gulp الملفَ <code>main.min.js</code> في كل مرة تشغِّل فيها المهمّة <code>useref</code>. إحدى الأمور الرائعة التي لم أخبرك عنها بعد هي أنَّ إضافة <code>gulp-useref</code> ستحوِّل جميع السكربتات الموجودة بين <code>‎&lt;!--build:‎</code> و <code>&lt;‎!--endbuild--‎&gt;</code> إلى ملف JavaScript وحيد الذي يُشير إلى <code>js/main.min.js</code> وذلك في صفحة <code>index.html</code>، أي أنَّ ملف <code>index.html</code> الناتج سيكون شبيهًا بما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5720_135" style="">
<span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;head&gt;&lt;/head&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"js/main.min.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	سنستعمل نفس الطريقة لجمع ملفات CSS:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5720_137" style="">
<span class="com">&lt;!--build:css css/styles.min.css--&gt;</span><span class="pln">
</span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"css/styles.css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"css/another-stylesheet.css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="com">&lt;!--endbuild--&gt;</span></pre>

<p>
	يمكننا أيضًا تصغير ملف CSS الناتج، لكننا بحاجة إلى تثبيت الإضافة <a href="https://www.npmjs.com/package/gulp-cssnano" rel="external nofollow">gulp-cssnano</a>:
</p>

<pre class="ipsCode" id="ips_uid_5720_145">
npm install gulp-cssnano
</pre>

<p>
	الشيفرة التي سنضيفها إلى ملف <code>gulpfile.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_147" style="">
<span class="kwd">var</span><span class="pln"> cssnano </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-cssnano'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'useref'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/*.html'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">useref</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulpIf</span><span class="pun">(</span><span class="str">'*.js'</span><span class="pun">,</span><span class="pln"> uglify</span><span class="pun">()))</span><span class="pln">
    </span><span class="com">// CSS التصغير إذا كان الملف</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulpIf</span><span class="pun">(</span><span class="str">'*.css'</span><span class="pun">,</span><span class="pln"> cssnano</span><span class="pun">()))</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'dist'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ستحصل الآن على ملف CSS وملف JavaScript وحيد ومُصغّر في كل مرة تُشغِّل فيها المهمّة <code>useref</code>.
</p>

<h2 id="cssjavasctipt">
	تحسين دعم المتصفحات لخاصيات CSS وشيفرة JavaSctipt
</h2>

<p>
	نبدأ بتحسين دعم خاصيات CSS عبر مختلف المتصفحات. فمن المؤكد أنك رأيت شيفرة CSS مكتوبة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_4527_10" style="">
<span class="pun">.</span><span class="pln">navigation </span><span class="pun">{</span><span class="pln">
  display</span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="pln">webkit</span><span class="pun">-</span><span class="pln">box</span><span class="pun">;</span><span class="pln">
  display</span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="pln">ms</span><span class="pun">-</span><span class="pln">flexbox</span><span class="pun">;</span><span class="pln">
  display</span><span class="pun">:</span><span class="pln"> flex
</span><span class="pun">}</span></pre>

<p>
	ولابد أنك استصعبت - أثناء كتابة شيفرة CSS - البحث عن دعم كل خاصية من خاصيات CSS لمختلف المتصفحات وتساءلت عن وجود أداة تضيف السوابق الخاصة بدعم الخاصيات في المتصفحات الأخرى مثل ‎-webkit-box و ‎-ms-flexbox. الحل بسيط جدًا وهو استعمال الإضافة <a href="https://www.npmjs.com/package/gulp-autoprefixer" rel="external nofollow">gulp-autoprefixer</a> الموجودة لهذا الغرض. نفذ الأمر التالي لتثبيت هذه الإضافة:
</p>

<pre class="ipsCode" id="ips_uid_5720_156">
npm install gulp-autoprefixer --save-dev
</pre>

<p>
	أضف السطر الآتي إلى ملف <code>gulpfile.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_158" style="">
<span class="kwd">const</span><span class="pln"> autoprefixer </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-autoprefixer'</span><span class="pun">);</span></pre>

<p>
	تهيئة واستعمال هذه الإضافة - مع الإضافة <code>gulp-sass</code> والإضافة <code>browser-sync</code> التي تحدثنا عنهما في الأعلى - يكون بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_160" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">"styles"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  gulp
    </span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">"app/css/**/*.scss"</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">sass</span><span class="pun">().</span><span class="pln">on</span><span class="pun">(</span><span class="str">"error"</span><span class="pun">,</span><span class="pln"> sass</span><span class="pun">.</span><span class="pln">logError</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">autoprefixer</span><span class="pun">({</span><span class="pln">
        </span><span class="com">// دعم آخر إصدارين للمتصفح</span><span class="pln">
        browsers</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">"last 2 versions"</span><span class="pun">]</span><span class="pln"> 
      </span><span class="pun">})</span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">"css"</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">browserSync</span><span class="pun">.</span><span class="pln">stream</span><span class="pun">());</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	نحصل بذلك على شيفرة CSS السابقة عند كتابة:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_5720_162" style="">
<span class="pun">.</span><span class="pln">navigation </span><span class="pun">{</span><span class="pln">
  display</span><span class="pun">:</span><span class="pln"> flex
</span><span class="pun">}</span></pre>

<p>
	فقط لتصبح الشيفرة مدعومة على كافة المتصفحات التي لا تدعم خاصيات CSS محدَّدة مثل التي رأيناها للتو.
</p>

<p>
	<strong>ملاحظة</strong>: إن أردت استعمال الإضافة gulp-autoprefixer مع الإضافة gulp-cssnano (وإضافات أخرى)، فيمكنك استعمالهما سوية عبر استعمال الإضافة <a href="https://github.com/postcss/gulp-postcss" rel="external nofollow">gulp-postcss</a>. تمرر هذه الإضافة شيفرة CSS إلى عدة إضافات مع تحليل الشيفرة مرةً واحدةً مما يزيد من سرعة تنفيذ العملية.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_164" style="">
<span class="kwd">var</span><span class="pln"> postcss </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-postcss'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> gulp </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> autoprefixer </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'autoprefixer'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> cssnano </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'cssnano'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'css'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// CSS تحديد الإضافات المراد استعمالها مع شيفرة </span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> plugins </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        autoprefixer</span><span class="pun">({</span><span class="pln">browsers</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'last 2 version'</span><span class="pun">]}),</span><span class="pln">
        cssnano</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/css/*.css'</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">postcss</span><span class="pun">(</span><span class="pln">plugins</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'./dest'</span><span class="pun">));</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	اطلع على <a href="https://github.com/postcss/gulp-postcss" rel="external nofollow">توثيق الإضافة الرسمي</a> لمزيد من الأمثلة وكيفية الاستخدام.
</p>

<p>
	ننتقل الآن إلى تحسين دعم شيفرة JavaScript وأتحدث الآن عن دعم ميزات ES6 عبر مختلف المتصفحات. الحقيقة أن <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%85%D9%8A%D8%B2%D8%A7%D8%AA-%D8%A7%D9%84%D8%AC%D8%AF%D9%8A%D8%AF%D8%A9-%D9%81%D9%8A-es6-%D9%86%D8%B7%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA%D8%8C-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%B3%D9%87%D9%85%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%A8%D8%AF%D8%A6%D9%8A%D8%A9-r567/" rel="">الميزات التي يوفرها الإصدار ES6</a> (أو ECMAScript 6) مغرية جدًا لجميع مطوري الويب ولكن نقص الدعم في مختلف المتصفحات والإصدارات القديمة هو من أكبر العقبات أمام الاستفادة من تلك الميزات. انطلاقًا من ذلك، جاءت فكرة وجود محول يدعى transpiler والذي يحول من لغة برمجية معينة إلى برمجية أخرى (في حالتنا من ECMAScript 6 إلى ES2015 أو ما قبلها). المحول الذي سنختاره هنا هو المحول الشهير <a href="https://babeljs.io/" rel="external nofollow">Babel JS</a> الذي يحوي الكثير من الميزات والمدعوم بقوة من قبل المجتمع.
</p>

<p>
	سنستعمل الإضافة <a href="https://www.npmjs.com/package/gulp-babel" rel="external nofollow">gulp-babel</a> لهذا الغرض. ثبت الإضافة عبر الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_5720_173">
# Babel 6
npm install --save-dev gulp-babel
# Babel 7
npm install --save-dev gulp-babel@next @babel/core</pre>

<p>
	أضف الشيفرة التالية إلى ملف <code>gulpfile.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_175" style="">
<span class="kwd">var</span><span class="pln"> babel </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">"gulp-babel"</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">"default"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">"app/js/*.js"</span><span class="pun">)</span><span class="pln">
    </span><span class="com">// تحويل الشيفرة إلى الإصدار الأقدم</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">babel</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">"dist"</span><span class="pun">));</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	<strong>تنبيه</strong>: احرص على استدعاء <code>babel()‎</code> قبل إجراء أية عملية تصغير أو ضغط على شيفرة JavaScript.
</p>

<h2 id="-2">
	تحسين الصور
</h2>

<p>
	أظن أنك ستتوقع أننا سنحتاج إلى تثبيت إضافة لمساعدتنا في موضوع تحسين الصور، وهي <a href="https://www.npmjs.com/package/gulp-imagemin" rel="external nofollow">gulp-imagemin</a>. الضغط الذي ستوفره هذه الإضافة هو الضغط غير الفَقُود (lossless compression).
</p>

<pre class="ipsCode" id="ips_uid_5720_178">
npm install gulp-imagemin –save-dev
</pre>

<p>
	يمكننا تصغير صورة <code>png</code> و <code>jpg</code> و <code>gif</code> وحتى <code>svg</code> باستخدام إضافة gulp-imagemin. لننشِئ مهمّة <code>images</code> لهذا الغرض:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_180" style="">
<span class="kwd">var</span><span class="pln"> imagemin </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-imagemin'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/images/**/*.+(png|jpg|gif|svg)'</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">imagemin</span><span class="pun">())</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'dist/images'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ولأن كلُّ نوعٍ من أنواع الصور سيُحسّن بطريقةٍ مختلفة، فربما ترغب بإضافة بعض الخيارات إلى <code>imagemin</code> لتخصيص كيفية تحسين الصورة. على سبيل المثال، يمكننا إنشاء صورة GIF متداخلة (<a href="http://vesta.astro.amu.edu.pl/Library/WWW/Tutorial1/graphics/gif_files.html" rel="external nofollow">interlaced</a>) بضبط قيمة الخيار <code>interlaced</code> إلى <code>ture</code>.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_20" style="">
<span class="pln">gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  .pipe(imagemin({
      interlaced: true
    }))
  .pipe(gulp.dest('dist/images'))
});
</span></pre>

<p>
	إن كانت تريد إجراء عملية ضغط فقود (lossy compression)، والذي سيخفّض حجم الصورة بشكل كبيرة على حساب الجودة، فاستعمل الإضافة <a href="https://www.npmjs.com/package/imagemin-pngquant" rel="external nofollow">imagemin-pngquant</a>.
</p>

<pre class="ipsCode" id="ips_uid_5720_184">
npm install imagemin-pngquant –save-dev
</pre>

<p>
	خيار الضغط الذي توفره هذه الإضافة يتمتع بالذكاء والذي يدعى PNG quantization (توضيح صور PNG)، إذ يعمل على اللعب بالألوان التي يراها دماغنا على أنها تقريبًا متماثلة محولًا الصورة إلى حجم 256 أو 8 بت للألوان. أفضل شيء في هذه الإضافة هو أنها لن تعدل أي شيء على الصور إن لم تتحقق حدود معينة متعلقة بالجودة. سنعدل على المثال السابق لاستعمال pngquant()<code>‎</code> مع <code>imagemin</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_20" style="">
<span class="pln">var imagemin = require('gulp-imagemin');

gulp.task('default', function() {
    return gulp.src('app/images/*')
        .pipe(imagemin({
            progressive: true,
            use: [pngquant()]
        }))
        .pipe(gulp.dest('dist/images'));
});
</span></pre>

<p>
	على أي حال، عملية تحسين الصور هي عمليةٌ بطيئةٌ للغاية، ولا ترغب في تكرارها إلا إذا كان ذلك ضروريًا، ويمكننا تخزينها مؤقتًا باستخدام إضافة <a href="https://www.npmjs.com/package/gulp-cache" rel="external nofollow">gulp-cache</a>.
</p>

<pre class="ipsCode" id="ips_uid_5720_187">
npm install gulp-cache –save-dev
</pre>

<p>
	الشيفرة التي سنضيفها إلى ملف <code>gulpfile.js</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_189" style="">
<span class="kwd">var</span><span class="pln"> cache </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'gulp-cache'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(){</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/images/**/*.+(png|jpg|jpeg|gif|svg)'</span><span class="pun">)</span><span class="pln">
  </span><span class="com">// تخزين الصور المُحسّنة مؤقتًا</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">cache</span><span class="pun">(</span><span class="pln">imagemin</span><span class="pun">({</span><span class="pln">
      interlaced</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
    </span><span class="pun">})))</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'dist/images'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	انتهينا تقريبًا من عمليات التحسين، وبقي مجلدٌ أخير يجب علينا نقله من مجلد <code>app</code> إلى <code>dist</code> وهو مجلد الخطوط.
</p>

<p>
	لمزيد من التفاصيل حول تحسين الصور في موقعك، ننصحك بالإطلاع على مقال «<a href="https://academy.hsoub.com/apps/web/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D9%84%D9%80%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%A3%D8%AF%D8%A7%D8%A1-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D8%B9%D9%84%D9%89-%D9%85%D9%88%D9%82%D8%B9%D9%83-%E2%80%93-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-1-r88/" rel="">دليلك الشامل لتحسين أداء الصور على موقعك</a>».
</p>

<h2 id="dist">
	نسخ الخطوط إلى مجلد dist
</h2>

<p>
	لن تحتاج الخطوط إلى أيّة عمليات تحسين، وكل ما علينا فعله هو نسخها إلى مجلد <code>dist</code>. يمكننا نسخ الملفات باستخدام Gulp ببساطة باستخدام الدالتين <code>gulp.src</code> و <code>gulp.dest</code> دون أيّة إضافات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_192" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'fonts'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> gulp</span><span class="pun">.</span><span class="pln">src</span><span class="pun">(</span><span class="str">'app/fonts/**/*'</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">.</span><span class="pln">pipe</span><span class="pun">(</span><span class="pln">gulp</span><span class="pun">.</span><span class="pln">dest</span><span class="pun">(</span><span class="str">'dist/fonts'</span><span class="pun">))</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	سينسخ Gulp مجلد fonts من <code>app</code> إلى <code>dist</code> في كل مرة تشغِّل فيها الأمر <code>gulp fonts</code>. أصبحت لدينا ست مهام مختلفة في ملف <code>gulpfile.js</code>، ويجب علينا استدعاؤها يدويًا باستخدام سطر الأوامر. ربما نفكّر بربط المهام جميعًا إلى أمرٍ وحيد، لكن قبل ذلك لننظر إلى كيفية حذف الملفات المولّدة تلقائيًا.
</p>

<h2 id="-3">
	حذف الملفات المولدة تلقائيًا
</h2>

<p>
	لمّا كنّا نولِّد الملفات تلقائيًا، فعلينا أن نتأكد أنَّ الملفات التي لم تعد مستخدمةً لن تبقَ موجودةً دون علمنا. سنحتاج إلى استخدام <a href="https://www.npmjs.com/package/del" rel="external nofollow">del</a> لمساعدتنا في ذلك.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_20" style="">
<span class="pln">npm install del –save-dev
</span></pre>

<p>
	الدالة <code>del</code> تأخذ مصفوفةً من محارف التحديد (globs) التي تخبرها ما هي المجلدات التي يجب حذفها. يمكننا استخدامها كمهمّة في Gulp كما فعلنا من قبل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_195" style="">
<span class="kwd">var</span><span class="pln"> del </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'del'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'clean:dist'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> del</span><span class="pun">.</span><span class="pln">sync</span><span class="pun">(</span><span class="str">'dist'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	سيَحذف Gulp المجلد <code>dist</code> في كل مرة تُشغِّل فيها الأمر <code>gulp clean:dist</code>.
</p>

<p>
	<strong>ملاحظة</strong>: لا حاجة أن نقلق من حذف مجلد <code>dist/images</code> لأنَّ إضافة gulp-cache خزَّنت نسخةً مؤقتةً من الصور في نظامك. ستحتاج إلى إنشاء مهمّة منفصلة لحذف النسخة المؤقتة وليكن اسمها <code>cache:clear</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_197" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'cache:clear'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">callback</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> cache</span><span class="pun">.</span><span class="pln">clearAll</span><span class="pun">(</span><span class="pln">callback</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<h2 id="gulp-4">
	جمع مهام Gulp مع بعضها
</h2>

<p>
	ما فعلناه إلى الآن هو إنشاء مجموعتين منفصلتين من مهمات Gulp.
</p>

<p>
	الغرض من المجموعة الأولى هو المساعدة في التطوير، حيث حوّلنا ملفات Sass إلى CSS، وراقبنا تغيرات الملفات، وأعدنا تحميل الصفحة في متصفح الويب وقت الحاجة. أما المجموعة الثانية فكانت لتحسين الملفات الملحقة بالصفحة، حيث جهّزنا جميع الملفات للموقع الإنتاجي، وذلك بدمج ملفات CSS و JavaScript وتصغيرها، وتحسين الصور ونسخ الخطوط من <code>app</code> إلى <code>dist</code>.
</p>

<p>
	لقد وضعنا أول مجموعة من المهمات في بُنية يمكن تشغيلها باستخدام الأمر <code>gulp watch</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_199" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'watch'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'browserSync'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'sass'</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln">
  </span><span class="com">// ... </span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	أما المجموعة الثانية فتستخدم لإنشاء الموقع الإنتاجي، وهي تتضمن المهمات <code>clean:dist</code> و <code>sass</code> و <code>useref</code> و images <code>و </code>fonts<code>.</code>
</p>

<p>
	يمكننا إنشاء مهمة باسم build التي ستجمع كل ما سبق في مهمة واحدة.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_201" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'build'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[`</span><span class="pln">clean</span><span class="pun">`,</span><span class="pln"> </span><span class="pun">`</span><span class="pln">sass</span><span class="pun">`,</span><span class="pln"> </span><span class="pun">`</span><span class="pln">useref</span><span class="pun">`,</span><span class="pln"> </span><span class="pun">`</span><span class="pln">images</span><span class="pun">`,</span><span class="pln"> </span><span class="pun">`</span><span class="pln">fonts</span><span class="pun">`],</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(){</span><span class="pln">
  console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'Building files'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	للأسف لا يمكننا كتابة المهمّة <code>build</code> بهذه الطريقة لأن Gulp سيشغِّل المهمات المُمرَّرة كوسيطٍ ثانٍ إلى الدالة <code>task</code> معًا وليس بالترتيب.
</p>

<p>
	فهنالك احتمالٌ أن ينتهي تنفيذ المهمات <code>useref</code> أو <code>images</code> أو حتى <code>fonts</code> قبل إكمال المهمّة <code>clean</code> التي تُسبِّب حذف كامل مجلد <code>dist</code>! لذا لضمان أنَّ المهمات ستُنفَّذ بترتيبٍ صحيح، فسنحتاج إلى استخدام إضافة خارجية باسم <a href="https://www.npmjs.com/package/run-sequence" rel="external nofollow">Run Sequence</a>:
</p>

<pre class="ipsCode" id="ips_uid_5720_203">
npm install run-sequence –save-dev
</pre>

<p>
	وهذه هي البنية العامة لطريقة تشغيل سلسلة من المهمّات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_206" style="">
<span class="kwd">var</span><span class="pln"> runSequence </span><span class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span class="str">'run-sequence'</span><span class="pun">);</span><span class="pln">

gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'task-name'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">callback</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  runSequence</span><span class="pun">(</span><span class="str">'task-one'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'task-two'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'task-three'</span><span class="pun">,</span><span class="pln"> callback</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	عندما تستدعى المهمّة <code>task-name</code> فسيُشغِّل Gulp المهمّة <code>task-one</code> أولًا، وبعد انتهاء تنفيذها سيُشغِّل المهمة <code>task-two</code>، ثم <code>task-three</code> وهكذا.
</p>

<p>
	تسمح لك إضافة Run Sequence بتشغيل المهمات معًا إذا وضعتَها في مصفوفة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_208" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'task-name'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">callback</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  runSequence</span><span class="pun">(</span><span class="str">'task-one'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'tasks'</span><span class="pun">,</span><span class="str">'two'</span><span class="pun">,</span><span class="str">'run'</span><span class="pun">,</span><span class="str">'in'</span><span class="pun">,</span><span class="str">'parallel'</span><span class="pun">],</span><span class="pln"> </span><span class="str">'task-three'</span><span class="pun">,</span><span class="pln"> callback</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	في هذه الحالة، سيُشغِّل Gulp المهمّة <code>task-one</code>، وبعد انتهاء تنفيذها فسيُشغِّل جميع المهمات الموجودة في المصفوفة معًا، وجميع المهمات الموجودة في المصفوفة يجب أن ينتهي تنفيذها قبل تنفيذ <code>task-three</code>.
</p>

<p>
	لذا يمكننا الآن إنشاء مهمة التي تُشغِّل المهمّة <code>clean:dist</code> أولًا، ثم تتبعها بقية المهمات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_210" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'build'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">callback</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  runSequence</span><span class="pun">(</span><span class="str">'clean:dist'</span><span class="pun">,</span><span class="pln"> 
    </span><span class="pun">[</span><span class="str">'sass'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'useref'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'images'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'fonts'</span><span class="pun">],</span><span class="pln">
    callback
  </span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	ولجعل الملف متناسقًا، فسنستخدم نفس الطريقة مع أوّل مجموعة من المهمات، وسنستخدم الاسم <code>default</code> كاسمٍ للمهمّة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_5720_212" style="">
<span class="pln">gulp</span><span class="pun">.</span><span class="pln">task</span><span class="pun">(</span><span class="str">'default'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">callback</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  runSequence</span><span class="pun">([</span><span class="str">'sass'</span><span class="pun">,</span><span class="str">'browserSync'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'watch'</span><span class="pun">],</span><span class="pln">
    callback
  </span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span></pre>

<p>
	لماذا اخترنا الاسم <code>default</code>؟ لأنّ المهمّة ذات الاسم <code>default</code> ستُشغَّل إن كَتبتَ الأمر <code>gulp</code> دون تمرير اسم المهمة له، مما يوفِّر عليك بعض الوقت :-) .
</p>

<h2 id="-4">
	الخلاصة
</h2>

<p>
	بدأنا درسنا ونحن لا نعرف شيئًا عن Gulp، ثم كتبنا مهمةً بسيطةً لتحويل ملفات Sass إلى CSS ومراقبة ملفات HTML و JS، وتعلمنا كيف نشغِّل تلك المهمّة في سطر الأوامر باستخدام الأمر <code>gulp</code>.
</p>

<p>
	ثم بنينا بعد ذلك مهمّةً ثانيةً، ألا وهي <code>build</code>، والتي تُنشِئ المجلد <code>dist</code> لكي يحتوي على ملفات الموقع الإنتاجي، وحوّلنا ملفات Sass إلى CSS وأجرينا عمليات تحسين على ملحقات الصفحة، ونسخنا المجلدات الضرورية إلى مجلد <code>dist</code>؛ وتمكنّا من تنفيذ كل ما سبق بأمرٍ وحيد وهو <code>gulp build</code>.
</p>

<p>
	في النهاية، أنشأنا المهمّة <code>clean</code> التي تحذف المجلد <code>dist</code> وبالتالي سنحذف أيّة ملفات غير مستخدمة في الموقع. لا تقف عند هذا الحد! Gulp واسع جدًا وإمكانياته لا تنتهي، وأرى أنَّ عليك تصفّح الإضافات الخاصة به والموجودة في <a href="http://gulpjs.com/plugins" rel="external nofollow">الموقع الرسمي</a>، وعليك الاستعانة <a href="https://github.com/gulpjs/gulp/blob/master/docs/API.md" rel="external nofollow">بتوثيق <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> إن أردت رؤية توثيق دوال Gulp.
</p>

<h2 id="-5">
	المصادر
</h2>

<ul>
<li>
		تعتمد هذه المقالة اعتمادًا أساسيًا على مقالة <a href="https://css-tricks.com/gulp-for-beginners/" rel="external nofollow">Gulp for Beginners</a> لصاحبها Zell Liew
	</li>
	<li>
		قائمة <a href="https://github.com/gulpjs/gulp/blob/master/docs/README.md#articles" rel="external nofollow">بالمقالات</a> التي تتحدث عن Gulp
	</li>
	<li>
		<a href="https://github.com/substack/stream-handbook" rel="external nofollow">المجاري</a> (streams) في Node
	</li>
	<li>
		مقالة <a href="https://scotch.io/tutorials/automate-your-tasks-easily-with-gulp-js" rel="external nofollow">Automate Your Tasks Easily with Gulp.js</a> لصاحبها Justin Rexroad
	</li>
</ul>
]]></description><guid isPermaLink="false">663</guid><pubDate>Mon, 01 Apr 2019 15:05:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x623;&#x62F;&#x648;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x637;&#x648;&#x650;&#x651;&#x631; DevTools &#x641;&#x64A; Chrome</title><link>https://academy.hsoub.com/programming/workflow/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B7%D9%88%D9%90%D9%91%D8%B1-devtools-%D9%81%D9%8A-chrome-r554/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_10/hosub-youtube01-academy.png.5d3186c2edbcd117371c3c060c9ffb1e.png" /></p>

<p>
	<iframe allowfullscreen="" frameborder="0" gesture="media" height="394" src="https://www.youtube.com/embed/jhDFmUC0xG4?rel=0&amp;showinfo=0" width="700"></iframe>
</p>

<p>
	إن كنت مطور ويب فأنت تعاني حتماً من مشكلة اكتشاف الأخطاء ومعالجتها أو ما يعرف بـ debugging، فمثلاً إذا كان لديك خطأ في شيفرة JavaScript فهناك احتمال ضئيل أن يظهر لك المستعرض رقم السطر الذي يحوي الخطأ، وحتى إن أظهره لك فليس من الضروري أن يكون هذا السطر هو المسبب للخطأ. وإذا ما اتجهنا نحو أخطاء ومشاكل مظهر الصفحة CSS فالأمر أشبه بالتنجيم. فمثلاً إذا واجهت مشكلة في تنسيق الصفحة فالحل الوحيد هو العودة إلى ملف CSS والقيام ببعض التعديلات ومن ثم الرجوع إلى المستعرض لرؤية ما إذا كانت هذه التعديلات قد حلت المشكلة، وهكذا في رحلة مكوكية بين المحرر والمستعرض حتى تجد المشكلة. لكن باستخدام أدوات المطور DevTools تستطيع تتبع مشاكل المظهر بفعالية، واكتشاف أخطاء جافاسكربت بسهولة، بالإضافة إلى أنها تقدم لك إضاءات ومعلومات حول الأداء والتي يمكن استخدامها لتحسينه.
</p>

<p>
	<a href="https://github.com/HsoubAcademy/calendar" rel="external nofollow">الشيفرة المصدرية الخاصة بمثال الرزنامة</a>
</p>
]]></description><guid isPermaLink="false">554</guid><pubDate>Wed, 01 Nov 2017 10:40:00 +0000</pubDate></item><item><title>&#x62F;&#x644;&#x64A;&#x644;&#x643; &#x625;&#x644;&#x649; &#x627;&#x633;&#x62A;&#x639;&#x645;&#x627;&#x644; &#x628;&#x631;&#x646;&#x627;&#x645;&#x62C; Vagrant</title><link>https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A5%D9%84%D9%89-%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D8%AC-vagrant-r269/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_06/Vagrant.png.2fdea9957772a455fe8152f9b1593830.png" /></p>

<div id="wmd-preview-section-24">
	<p id="دليلك-إلى-استعمال-vagrant">
		Vagrant هو برنامج يُمكّنك من إنشاء وإعداد بيئات عمل خفيفة للتطوير عليها عن طريق تشغيل آلة وهمية.
	</p>

	<p style="text-align: center;">
		<img alt="Vagrant.png" class="ipsImage ipsImage_thumbnailed" data-fileid="23814" data-unique="hq4k3c05u" src="https://academy.hsoub.com/uploads/monthly_2017_06/Vagrant.png.bd8cbcfe0bf3c3fe68ec30d0df5b3d5d.png"></p>
</div>

<div id="wmd-preview-section-26">
	<h2 id="لماذا-أستعمل-vagrant">
		لماذا أستعمل Vagrant
	</h2>

	<p>
		إذا كنت مطور ويب فسيساعدك البرنامج على محاكاة بيئة الخادوم عن طريق تنصيب إحدى نسخ لينكس للخواديم على جهازك. كما يساعدك أيضًا على تجربة تطبيقات الويب خاصتك بدون خوف من الخطأ أو الخوف على جهازك. وإذا كنت تعمل ضمن فريق عمل فإنه سيجعل من العمل أسهل بجعل بيئات التطوير واحدة بنفس البرمجيات والأنظمة.
	</p>
</div>

<div id="wmd-preview-section-27">
	<h2 id="البدأ-في-استعمال-vagrant">
		البدء في استعمال Vagrant
	</h2>

	<p>
		قبل البدء يجب أن يكون لديك برنامج للآلات الوهمية مثبت ويفضل أن يكون <a href="https://www.virtualbox.org/" rel="external nofollow">Virtualbox</a>. سيأتي ذكر كيفية ربطه مع برامج أخرى في آخر المقالة.
	</p>
</div>

<div id="wmd-preview-section-28">
	<p>
		بعد تثبيت Virtualbox يمكنك تثبيت النسخة المناسبة من Vagrant <a href="https://www.vagrantup.com/downloads.html" rel="external nofollow">من هنا</a>. 
	</p>

	<p>
		أنشأ مجلدًا جديدًا لبيئة العمل خاصتك. وادخل إليه من الطرفية عن طريق الأمر:
	</p>
</div>

<div id="wmd-preview-section-29">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2762_7">
<span class="pln">$ cd myfirst_project_dir</span></pre>

	<p>
		ثم اكتب الأمر التالي:
	</p>
</div>

<div id="wmd-preview-section-30">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2762_17">
<span class="pln">$ vagrant init ubuntu/trusty32</span></pre>

	<p>
		ستلاحظ أنه وفي أول مرة فقط بدأ بتحميل الملفات الخاصة بهذه الآلة وستلحظ أيضًا إنشاء ملف في هذا المجلد باسم <span style="font-family:courier new,courier,monospace;">Vagrantfile</span>.
	</p>

	<p>
		بعد الانتهاء من التحميل قم بتشغيل الآلة الوهمية عن طريق الأمر التالي مع التأكد أنك ما زلت في نفس المجلد :
	</p>
</div>

<div id="wmd-preview-section-31">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2762_19">
<span class="pln">$ vagrant up</span></pre>

	<p>
		انتظر قليلًا، بعد الانتهاء، مبارك لك تم تشغيل نظام أوبنتو 14.04 للخادم.
	</p>
</div>

<div id="wmd-preview-section-32">
	<h2 id="بدأ-العمل">
		بدأ العمل
	</h2>

	<p>
		يمكنك الآن للتحكم في النظام كتابة الأمر التالي :
	</p>
</div>

<div id="wmd-preview-section-33">
	<pre class="ipsCode" id="ips_uid_5029_7">
$ vargant <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr></pre>

	<p>
		وسيتم الدخول إلى جلسة الطرفية عن طريق بروتوكول <a href="https://en.wikipedia.org/wiki/Secure_Shell" rel="external nofollow"><abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr></a> . <br>
		يمكنك الآن كتابة أوامر لنظام أوبنتو كما تشاء. <br>
		يمكنك لتثبيت حزمة LAMP
	</p>
</div>

<div id="wmd-preview-section-34">
	<pre class="ipsCode" id="ips_uid_5029_9">
$ sudo apt-get install lamp-server^</pre>

	<p>
		يمكنك تثبيت أي برامج أو تطبيقات عن طريق سطر الأوامر يمكنك إذا أردت تثبيت Ngnix الاطلاع على <a href="https://academy.hsoub.com/devops/web-servers/nginx/%D8%AA%D9%86%D8%B5%D9%8A%D8%A8%D8%8C-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-nginx-%D9%83%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D9%88%D9%8A%D8%A8-r1/" rel="">هذا الدرس</a> اتبع الإرشادات الخاصة بأوبنتو لأن الصندوق الذي استعملناه هو الخاص بأوبنتو (كما سيأتي لاحقًا في شرح الصناديق). <br>
		يمكنك أيضًا تثبيت phpmyadmin كما يشرح <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81-%D8%AA%D9%8F%D8%AB%D8%A8%D9%91%D9%90%D8%AA-%D9%88%D8%AA%D8%A4%D9%85%D9%91%D9%90%D9%86-phpmyadmin-%D8%B9%D9%84%D9%89-ubuntu-1404-r35/" rel="">الدرس لتالي</a>.
	</p>
</div>

<div id="wmd-preview-section-35">
	<h2 id="المجلدات-المشتركة">
		المجلدات المشتركة
	</h2>

	<p>
		انتهيت من إعداد بيئة العمل تريد الآن البدأ في البرمجة ولكن هل ستضطر للدخول إلى جلسة الطرفية هذه كل مرة والعمل عن طريق محررات نصية كـ vim كي تستطيع العمل؟؟ <br>
		الإجابة هي لا ففي الحقيقة المجلد الذي مساره داخل البيئة الوهمية /vagrant هو نفسه المجلد الذي أنشأت فيه الآلة في البداية أي المجلد الذي يتواجد بداخله ملفVagrantfile. <br>
		ولتتأكد من كلامي هذا أنشأ في المجلد الحالي ملفًا نصيًا اسمه foo.txt ثم ادخل الآن إلى جلسة الطرفية الخاصة بالآلة الوهمية واكتب :
	</p>
</div>

<div id="wmd-preview-section-36">
	<pre class="ipsCode" id="ips_uid_5029_11">
$ cd /vagrant
$ ls</pre>

	<p>
		ستفاجئ بوجود الملف الذي أنشأته سابقًا وبهذا يمكننا Vagrant من العمل على المحررات التي نفضلها من واجهتنا الرسومية ومشاركة كل ما نعمله مع الآلة الضيف. <br>
		يمكنك أيضًالمشاركة مجلدات أخرى غير هذا المجلد كتابة الآتي داخلVagrantfile :
	</p>
</div>

<div id="wmd-preview-section-37">
	<pre class="ipsCode" id="ips_uid_5029_13">
  config.vm.synced_folder "src/", "/srv/website"</pre>

	<p>
		حيث أن المسار الأول هو مسار المجلد الذي تريد مشاركته على آلتك المضيفة والمسار الثاني هو مسار المجلد الموجود في الآلة الوهمية.
	</p>
</div>

<div id="wmd-preview-section-38">
	<h2 id="تهيئة-الشبكة">
		تهيئة الشبكة
	</h2>

	<p>
		الآن بعد تثبيت apache مع حزمة LAMP تريد تصفح الموقع المتواجد على الخادوم على الآلة الضيف من على متصفحك من جهازك فكيف تفعل هذا. <br>
		يمكنك فعل هذا بتعديل ملف Vagrantfile بحيث سيشبه الآتي :
	</p>
</div>

<div id="wmd-preview-section-39">
	<pre class="ipsCode" id="ips_uid_5029_15">
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty32"
  config.vm.network :forwarded_port, guest: 80, host: 4567
end</pre>

	<p>
		اكتب الأمر التالي في حاسوبك (ليس بداخل الآلة الوهمية) داخل مجلد الآلة الوهمية:
	</p>
</div>

<div id="wmd-preview-section-40">
	<pre class="ipsCode" id="ips_uid_5029_17">
$ vagrant reload</pre>

	<p>
		الآن يمكنك تصفح موقعك من على الرابط التالي <a href="http://127.0.0.1:4567/" rel="external nofollow">http://127.0.0.1:4567</a> داخل متصفحك.
	</p>
</div>

<div id="wmd-preview-section-41">
	<h2 id="جعل-المجلد-الافتراضي-لـapache-في-vagrant">
		جعل المجلد الافتراضي لـapache في/vagrant
	</h2>

	<p>
		أنت الآن تريد إضافة ملفات البرمجة الخاصة بك وبدأت العمل عليها في المُجلّد/vagrant ولكن لا تزال هناك مشكلة فـapache يحدد المُجلّد /var/www/htmlكمُجلّد افتراضي توجد عليه الملفات التي سوف تمثل واجهة الموقع لذا علينا أن نجعل المُجلّد الافتراضي هو /vagrant/my_awesome_project والذي ستضع عليه ملفات الـPHP الخاصة بمشروعك. <br>
		في البداية أنشئ في المُجلّد الذي تتواجد فيه الآلة الافتراضية مُجلّدًا فرعيًا وسمه my_awesome_project ثم اكتب الأمر التالي في جلسة الطرفية للآلة الضيف:
	</p>
</div>

<div id="wmd-preview-section-42">
	<pre class="ipsCode" id="ips_uid_5029_19">
$ sudo nano /etc/apache2/sites-available/000-default.conf</pre>

	<p>
		أضف الآتي:
	</p>
</div>

<div id="wmd-preview-section-43">
	<pre class="ipsCode" id="ips_uid_5029_21">
DocumentRoot /vagrant/my_awesome_project</pre>

	<p>
		احفظ التغييرات عن طريق الضغط على Ctrl + X ثم اكتب الأمر التالي:
	</p>
</div>

<div id="wmd-preview-section-44">
	<pre class="ipsCode" id="ips_uid_5029_23">
$ sudo nano /etc/apache2/apache2.conf</pre>

	<p>
		أضف الآتي:
	</p>
</div>

<div id="wmd-preview-section-45">
	<pre class="ipsCode" id="ips_uid_5029_25">
&lt;Directory /vagrant&gt;
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
&lt;/Directory&gt;</pre>

	<p>
		احفظه عن طريق الضغط على Ctrl + X ثم اكتب الأمر التالي لإعادة تشغيل الخادوم والعمل بالتغييرات :
	</p>
</div>

<div id="wmd-preview-section-46">
	<pre class="ipsCode" id="ips_uid_5029_27">
sudo service apache2 restart</pre>

	<p>
		مبارك لك الآن يمكنك الدخول إلى المُجلّد الذي يحتوي الآلة الوهمية والدخول إلى المُجلّد المسمى my_awesome_project بداخله وبدأ العمل ومشاهدة التغييرات مباشرة على: <br><a href="http://127.0.0.1:4567/" rel="external nofollow">http://127.0.0.1:4567</a>
	</p>
</div>

<div id="wmd-preview-section-47">
	<h2 id="إغلاق-الآلة">
		إغلاق الآلة
	</h2>

	<p>
		بعد الإنتهاء من العمل سيتوجب عليك إغلاق الآلة الوهمية ويمكن هذا بواحد من ثلاث أوامر داخل دليل الآلة:
	</p>
</div>

<div id="wmd-preview-section-48">
	<pre class="ipsCode" id="ips_uid_5029_29">
$ vagrant suspend
$ vagrant halt
$ vagrant destroy</pre>

	<ol>
<li>
			<p>
				الأمر الأول يقوم بحفظ حالة الآلة كما هي وعند الإقلاع مرة أخرى بالأمرvargant up يكون الإقلاع سريعًا لأنه فقط يقوم بإيقاظ الآلة.
			</p>
		</li>
		<li>
			<p>
				الأمر الثاني يعمل على إغلاق الآلة بالكامل وإغلاق كافة البرامج التي كانت تعمل على الآلة وأيضًا يتم الإقلاع مرة أخرى بالأمر vagrant up .
			</p>
		</li>
		<li>
			<p>
				الأمر الثالث يمحو الآلة مع كل شيء داخل المجلد الذي يحتويها.
			</p>
		</li>
	</ol>
</div>

<div id="wmd-preview-section-49">
	<h2 id="الصناديق-boxes">
		الصناديق (Boxes)
	</h2>

	<p>
		يستعمل Vagrant الصناديق بدلًا من ترجمة ملفات الآلة الوهمية من الصفر مما يؤدي إلى ضياع الكثير. <br>
		تعتبر الصناديق كالأنظمة والإعدادات معها المجهزة مسبقًا كي يتم استعمالها مباشرة. <br>
		يعد الأمر الآتي الذي استعملناه في أول الدرس مثالًا على استخدام أحد الصناديق :
	</p>
</div>

<div id="wmd-preview-section-50">
	<pre class="ipsCode" id="ips_uid_5029_31">
$ vagrant init ubuntu/trusty32</pre>

	<p>
		والذي من المفترض أن ينشئ آلة وهمية في المجلد الحالي اتخدامًا للصناديق فقد استعمل الصندوق المسمى بـubuntu/trusty32 <br>
		حالما يتم تنزيل الصندوق يمكنك استعماله في أي مكان وفي أي آلة تنشؤها ويمكنك إضافة أي صندوق جديد عن طريق الأمر التالي:
	</p>
</div>

<div id="wmd-preview-section-51">
	<pre class="ipsCode" id="ips_uid_5029_33">
$ vagrant box add box_name</pre>

	<p>
		وفائدة هذه الصناديق هي استعمال إعدادات وأنظمة جاهزة ومختلفة فمثلًا إذا أردت استعمال CentOS بدلًا من أوبونتو يمكنك استبدال اسم الصندوق بـdanmikita/centos . <br>
		يمكنك البحث عن الصناديق المتوفرة وأسمائها من خلال الرابط التالي: <br><a href="https://atlas.hashicorp.com/boxes/search" rel="external nofollow">https://atlas.hashicorp.com/boxes/search</a>
	</p>
</div>

<div id="wmd-preview-section-52">
	<h2 id="التجهيز-provisioning">
		التّجهيز (Provisioning)
	</h2>

	<p>
		يمكنك التّجهز (Provisioning) من تنفيذ أوامر معينة على الآلة الوهمية بدون الدخول إليها ويمكن ذلك عن طريق التعديل في ملف Vagrantfile وذلك يمكنك من استعمال نفس البرامج والإعدادات على جميع الآلات. <br>
		لتتمكن من استعمال التزويد عليك إضافة الأمر التالي إلى ملف Vagrantfile لـ:
	</p>
</div>

<div id="wmd-preview-section-53">
	<pre class="ipsCode" id="ips_uid_5029_35">
  config.vm.provision :shell, path: "bootstrap.sh"</pre>

	<p>
		هذا الأمر يجعل من ملف bootstrap.sh ملفًا يعمل عند تشغيل الآلة. هناك مجموعة كبيرة أخرى من الأوامر يمكنك الاطلاع عليها من التوثيق الرسمي للبرنامج. <br>
		يمكنك تفعيل التزويد في الآلة التي تعمل الآن عن طريق الأمر التالي:
	</p>
</div>

<div id="wmd-preview-section-54">
	<pre class="ipsCode" id="ips_uid_5029_37">
vagrant reload --provision</pre>

	<p>
		 
	</p>
</div>

<div id="wmd-preview-section-55">
	<h2 id="تغيير-virtualbox">
		تغيير Virtualbox
	</h2>

	<p>
		يمكنك بكل بساطة استعمال أي برنامج محاكاة <a href="https://docs.vagrantup.com/v2/providers/index.html" rel="external nofollow">مدعوم</a> كـبرنامج VMware على سبيل المثال عن طريق الأمر التالي مع أمر vagrant up:
	</p>
</div>

<div id="wmd-preview-section-56">
	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2762_10">
<span class="pln">$ vagrant up --provider=vmware_fusion</span></pre>

	<h2>
		مشاركة الآلة
	</h2>

	<p>
		يمكنك مشاركة الآلة خاصتك مع فريق العمل وجعلهم يتمكنون من مراقبتها أو التحكم بها من أي مكان. 
	</p>

	<p>
		هناك ثلاثة طرق للمشاركة: 
	</p>

	<h3>
		مشاركة HTTP
	</h3>

	<p>
		ويشارك هذا الآلة عبر منفذ HTTP ويمكن عمل هذا عبر تنفيذ الأمر vagrant share وبعد ذلك وبعد انتهاء الأمر سيظهر في آخره رابطًا يمكنك مشاركته مع فريق عملك. 
	</p>

	<blockquote class="ipsQuote" data-ipsquote="">
		<div class="ipsQuote_citation">
			Quote
		</div>

		<div class="ipsQuote_contents ipsClearfix">
			<p>
				 ملحوظة : هذا الرابط يمكن لأي شخص تصفحه لذا كن حذرًا لمن تعطي الرابط.  
			</p>
		</div>
	</blockquote>

	<h3>
		مشاركة <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr>
	</h3>

	<p>
		يمكن هذا عن طريق كتابة الأمر: <br>
		 
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2762_12">
<span class="pln">vagrant share --<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> </span></pre>

	<p>
		سيطلب منك هذا الأمر كتابة كلمة السر التي سيتم التأكد بها من المتصل. بعد الانتهاء من الأمر يمكنك التوصل إلى الآلة من حاسوب آخر عن طريق الأمر: <br>
		 
	</p>

	<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2762_14">
<span class="pln">vagrant connect --<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> NAME </span></pre>

	<p>
		حيث NAME اسم الآلة الذي ظهر عند نهاية أمر vagrant share --<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> <br>
		 
	</p>

	<blockquote class="ipsQuote" data-ipsquote="">
		<div class="ipsQuote_citation">
			Quote
		</div>

		<div class="ipsQuote_contents ipsClearfix">
			<p>
				 ملحوظة تتطلب هذه الطريقة أن يكون vagrant مثبتًا على الجهاز الآخر  
			</p>
		</div>
	</blockquote>

	<h3>
		مشاركة عامة
	</h3>

	<p>
		وهي تشارك جميع المنافذ الممكنة ويكون ذلك عن طريق الأمرvagrant share ثم كتابة الأمر vagrant connect NAME على الجهاز المتحكم حيث NAME هو اسم الآلة الذي يظهر في نهاية تنفيذ الأمر vagrant share . 
	</p>

	<blockquote class="ipsQuote" data-ipsquote="">
		<div class="ipsQuote_citation">
			Quote
		</div>

		<div class="ipsQuote_contents ipsClearfix">
			<p>
				 ملحوظة: هذه الطريقة ليست آمنة تمامًا.
			</p>
		</div>
	</blockquote>

	<p>
		 
	</p>
</div>

<div id="wmd-preview-section-57">
	<h2 id="الخاتمة">
		الخاتمة
	</h2>

	<p>
		يمكنك إنشاء أي عدد من الآلات في مُجلّدات مختلفة والعمل عليها جميعًا أو على واحدة منها واستعمال أي صناديق تريد معها وإضافة إعدادات معينة للتزويد ونشرها مع فريق العمل ليتسنى لهم ضبط آلتهم كما هو عندك ومشاركة آلتك عن بعد كي يتحكم جميع فريق العمل في آلة واحدة .
	</p>
</div>

<div id="wmd-preview-section-58">
	<h2 id="المراجع">
		المراجع
	</h2>

	<ul>
<li>
			<p>
				<a href="https://docs.vagrantup.com/v2/" rel="external nofollow">https://docs.vagrantup.com/v2/</a>
			</p>
		</li>
		<li>
			<p>
				<a href="http://stackoverflow.com/questions/5891802/how-do-i-change-the-root-directory-of-an-apache-server" rel="external nofollow">http://stackoverflow.com/questions/5891802/how-do-i-change-the-root-directory-of-an-apache-server</a>
			</p>
		</li>
		<li>
			<p>
				<a href="https://help.ubuntu.com/community/ApacheMySQLPHP" rel="external nofollow">https://help.ubuntu.com/community/ApacheMySQLPHP</a>
			</p>
		</li>
	</ul>
</div>
]]></description><guid isPermaLink="false">269</guid><pubDate>Wed, 05 Jul 2017 08:10:01 +0000</pubDate></item><item><title>&#x645;&#x62E;&#x637;&#x637;&#x627;&#x62A; &#x627;&#x644;&#x641;&#x626;&#x627;&#x62A; (Class Diagram) &#x641;&#x64A; &#x644;&#x63A;&#x629; &#x627;&#x644;&#x646;&#x645;&#x630;&#x62C;&#x629; &#x627;&#x644;&#x645;&#x648;&#x62D;&#x62F;&#x629; UML</title><link>https://academy.hsoub.com/programming/workflow/%D9%85%D8%AE%D8%B7%D8%B7%D8%A7%D8%AA-%D8%A7%D9%84%D9%81%D8%A6%D8%A7%D8%AA-class-diagram-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D9%86%D9%85%D8%B0%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D9%88%D8%AD%D8%AF%D8%A9-uml-r307/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2016_04/uml-class-diagram.png.b3d58df7686bce026b64619d422ef392.png" /></p>
<p dir="rtl">
	مخطط الفئات (classes) هو جزءٌ مهمٌ جدًا من لغة النمذجة الموحدة <a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language" rel="external nofollow">UML</a>، وهو مخطط هيكلي مهمته عرض الفئات بنظامٍ معيّن مع جميع العلاقات التي تربط بينها، وهو -برأيي- أشهر نوع من المخططات في هندسة البرمجيات.
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="uml-class-diagram.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14973" data-unique="0sqzm18rq" src="https://academy.hsoub.com/uploads/monthly_2016_04/uml-class-diagram.png.19fc591136367ab0ba7f0c7fcd0d6a6a.png">
</p>

<p dir="rtl">
	يساعدك رسم مخطط الفئات على رؤية المشكلة بأفقٍ أوسع؛ وعندما تكتبها، فستفرِّغ مساحةً في رأسك للأفكار الجديدة. وتُسهِّل أيضًا فهم هيكلية الفئات من الآخرين عندما تناقش المشكلة معهم. الفكرة هي أنني أنسى عادةً بنية المخططات عندما أحاول قراءة أحد المخططات التي رسمها غيري، فلهذا قررت كتابة هذه المقالة لعلها تذكرني بها في المستقبل.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة علوم الحاسوب
		</p>

		<p class="banner-subtitle">
			دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/computer-science/" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة علوم الحاسوب" src="https://academy.hsoub.com/learn/assets/images/courses/computer-science.png">
	</div>
</div>

<h2 dir="rtl">
	الفئة – Class
</h2>

<p dir="rtl">
	المكون الأساسي لهذه المخططات هو مخطط الفئة، التي تَظهَر على شكل عقدة (node) وعادةً كصناديق (boxes)، يمكن أن يُعرَّف لكل صنف دوال (methods) وخاصيات (attributes)، كما هو موضَّح بالشكل أدناه:
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="class2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14967" data-unique="vrvfqbqwo" src="https://academy.hsoub.com/uploads/monthly_2016_04/class2.png.ebe81eb5e21d09a4c382ddc04e832f3b.png">
</p>

<h2 dir="rtl">
	الوراثة – Inheritance
</h2>

<p dir="rtl">
	وراثة الفئات -في ما يتعلق بمخططات UML- هي علاقة تعميم (generalization) التي تمثل علاقة "هو" (is a) على مستوى الفئة، المخطط الآتي يُظهِر كيفية رسم التعميم.
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="inheritance.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14970" data-unique="6bo6ihnp5" src="https://academy.hsoub.com/uploads/monthly_2016_04/inheritance.png.4e92a3e8a6a68866d78e504d6687a7d6.png">
</p>

<h2 dir="rtl">
	التطبيق – Realization
</h2>

<p dir="rtl">
	هنالك علاقة مختلفة في UML للواجهات (interfaces)، فالوراثة من واجهة تسمى "implementation" التي هي علاقة "تطبيق" (realization) في مخططات UML. تمثيلها الشكلي مشابه للوراثة، إلا أنَّ الخط مقطّع (dashed)، ويجب تحديد أنَّ الواجهة هي «مجرَّدة» (abstract) – أي أنَّ اسمها مكتوبٌ بخطٍ مائل؛ كما هو مبيّن في هذا الرسم.
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="realization.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14971" data-unique="vdlxlslxp" src="https://academy.hsoub.com/uploads/monthly_2016_04/realization.png.8831c3542949d627993ce2b75ba22154.png">
</p>

<h2 dir="rtl">
	الارتباط – Association
</h2>

<p dir="rtl">
	شكل آخر من أشكال العلاقات في مخططات الفئات هو الارتباط (association)، وهو علاقة على مستوى الكائنات (object-level) أي أنه يحدث بين كائناتٍ لأصنافٍ مرتبطةٍ؛ لذا تُمثَّل كل العلاقة كعائلة من الوصلات (links). هنالك عدة أنواع من الارتباط مُحدَّدة أكثر (التجميع aggregation و التألف composition).
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="association.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14965" data-unique="3h1y8pcrh" src="https://academy.hsoub.com/uploads/monthly_2016_04/association.png.10ed11ecf3dd1d3be17e1065b8d545de.png">
</p>

<h2 dir="rtl">
	التجميع – Aggregation
</h2>

<p dir="rtl">
	التجميع هو شكل أكثر تحديدًا وتخصيصًا من الارتباط. وهو علاقة "لديه" (has a)؛ التمثيل الرسومي لهذه العلاقة هو الآتي:
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="aggregation.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14964" data-unique="24czanmzm" src="https://academy.hsoub.com/uploads/monthly_2016_04/aggregation.png.f19dab037f3c034f23ca0cac94e6333c.png">
</p>

<h2 dir="rtl">
	التألف – Composition
</h2>

<p dir="rtl">
	شكل أكثر تخصيصًا من التجميع هو التألف (composition) فبدلًا من علاقة "لديه" (has a) تكون العلاقة هي "يملك" (owns a). وهذا ملائمٌ للعلاقات التي لا يمكن أن يتواجد فيها كائن إلا كجزءٍ من كائنٍ آخر. على سبيل المثال، إن كنت هنالك طائرة تملك جناحًا فهذا تألف، فماذا ستفعل بالجناح لوحده؟ لكن إن كانت هنالك بركة فيها بعض البط فهذا تجميع، لأنه يملك للبط أن يعيش دون بركة (وإن لم يكن سعيدًا بذلك)، والبركة ستبقى بركة حتى لو لم يكن فيها بط؛ التمثيل الرسومي لعملية التألف هو مثل التجميع، لكن المُعيَّن مملوء وليس مُفرَّغ.
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="composition.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14968" data-unique="bb3m60cgb" src="https://academy.hsoub.com/uploads/monthly_2016_04/composition.png.428d797c67c3532408014676cef8225f.png">
</p>

<h2 dir="rtl">
	الاعتمادية – Dependency
</h2>

<p dir="rtl">
	آخر نوع من العلاقات هو "الاعتمادية" (dependency) وهو أضعف من الارتباط (association) ويقول: إن كانت الفئة تستعمل فئةً أخرى، فهي تعمد عليها.
</p>

<p dir="rtl">
	يكون من المناسب استعمالها في حالات تكون نسخةٌ من الفئةِ مخزنةً في متغيرٍ محلي في دالة فئة أخرى، أو إذا استعمِلَت دالةٌ ثابتةٌ (static method)؛ لذا لن تكون الفئات مرتبطةً، لكن واحدة تعتمد على الأخرى.
</p>

<p dir="rtl" style="text-align: center;">
	<img alt="dependency.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14969" data-unique="1wodpe9pn" src="https://academy.hsoub.com/uploads/monthly_2016_04/dependency.png.dfb05b029f19d903357771da9c65de46.png">
</p>

<h2 dir="rtl">
	خلاصة
</h2>

<p dir="rtl">
	صممت كل الأمثلة السابقة باستخدام محرر مفتوح المصدر باسم <a href="http://live.gnome.org/Dia" rel="external nofollow">Dia</a>، وأنا أنصح باستخدامه. ولأنه محرر رائع، فهذه صورة شاملة لجميع أنواع العلاقات إن أحببت طباعتها.
</p>

<p dir="rtl" style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="14966" href="https://academy.hsoub.com/uploads/monthly_2016_04/cheat_sheet4.png.dcd6a48c686e67d44310470fc32b4b3c.png" rel="" data-fileext="png"><img alt="cheat_sheet4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="14966" data-unique="oluefgki2" src="https://academy.hsoub.com/uploads/monthly_2016_04/cheat_sheet4.thumb.png.7d8b508ac85a576be707554afe9a46ab.png"></a>
</p>

<p dir="rtl">
	ترجمة -وبتصرّف- للمقال <a href="http://radek.io/2011/08/13/uml-class-diagram/" rel="external nofollow">UML Class Diagram</a> لصاحبه Radek Pazdera.
</p>
]]></description><guid isPermaLink="false">307</guid><pubDate>Tue, 12 Apr 2016 15:02:00 +0000</pubDate></item><item><title>&#x625;&#x62F;&#x627;&#x631;&#x629; &#x625;&#x636;&#x627;&#x641;&#x627;&#x62A; vim</title><link>https://academy.hsoub.com/programming/workflow/%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A5%D8%B6%D8%A7%D9%81%D8%A7%D8%AA-vim-r77/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_05/vim.png.aae209ebddc255f9ecc637815ba85912.png" /></p>

<p>محرّرُ Vim يتمتّع بشهرة واسعة، بفضل هذه الشهرة أصبح يُعدّ من أوائل المحرّرات التي يُمكن للمستخدم أن يُخصّصها ويُضيف عليها كل ما من شأنه أن يجعل التّحرير مُريحاً وسهلاً سواء شكلاً أو أداءً. لقد تحدّثنا سابقاً عن الشّكل والمظهر، وقد حان الوقتُ للغوص في أعماق الإضافات التي تجعل التحرير لعبة في كثير من الأحيان بل هناك بعض الإضافات التي ستندم على أنّك لم تعرفها في كلّ هذه السنين منذ بداية استخدامك للحاسب، مُعظم الإضافات تتّبع فلسفة 'اجعلها أسرع وأبسط' وهذا يعني أنّك ستجدُ ضالّتك في هذا الدّرس إذا كنت تبحث عن تحسين أدائك وزيادة إنتاجيّتك إذ ستتعلّم كيف تديرُ الإضافات من تثبيت وتحديث إلى طرق حذفها.</p><p dir="rtl">صحيح أن المُحرّر ممتازٌ جدّا في ما يتعلق بزيادة الإنتاجية حتى بدون أي إضافات (كما رأينا في الدّرسين السّابقين)، لكنّك بالإضافات قادرٌ على أخذ المُحرّر إلى المستوى المُتقدّم بشكل جدّ ملاحظ.</p><h2 dir="rtl">ماهي إضافات vim بالضبط؟</h2><p dir="rtl">لا أظنّ أنّك قد تسألُ هذا السؤال، فنحن محاطون بالإضافات في كلّ مكان من إضافات المتصفّح إلى تطبيقات الهواتف الذكيّة، لكن في حال سألت هذا السّؤال جديّا، ففكّر في الإضافة على أنها أداة مساعدة تؤدّي عملا معيّنا أو تساعدُ في القيام بأمر ما، الشيء الذي يُسهّل ويُسرع عملية الإنتاج، وقد أعطيتك إضافات المتصفّح كمثال، و هذا بالضبط ما تفعله إضافات vim، أي تسريع عملية الإنتاج (الكتابة).</p><p dir="rtl">الإضافات الخاصّة بالمحرّر يُمكن أن تكون عامّة أو مُخصّصة للغة برمجة ما، لبيئة ما أو إطار عمل معيّن.</p><p dir="rtl">معظم الإضافات مُطوّرة من مُبرمجين مُستقلّين عن مُطوري المُحرّر، وكذلك تستطيع أنت أن تُبرمج إضافة خاصّة بك سواء بلغة Vimscript أو بلغتك إذا كنت تجيد لغات مثل روبي، بايثون، Lua. مع ملاحظة أن الإضافات التي لم تُبرمج بلغة Vimscript عادة ما تكون بلغة بايثون.</p><h2 dir="rtl">تثبيت الإضافات</h2><p dir="rtl">أولا عليك أن تعرف بأن الإضافات ليست إلا ملفّات برمجيّة وتنصيبها لمُحرّر Vim أمر في غاية السهولة، ويُمكن ذلك بعدّة طُرق سواء بأداة pathogen الّتي تسهّل إدارة ملفّات الإضافات البرمجيّة حيثُ تقوم بتنظيم الملفّات والإضافات لأجل تَيْسِيرِ تحديثها وحذفها.</p><p dir="rtl">كذلك يُمكن فعل نفس الأمر باستخدام أداة Vundle التي استُلهمت من مشروع Bundler الخاص بإدارة جواهر روبي Rubygems. مع Vundle يمكنك ضبط إعدادات الإضافات في ملف vimrc، يُمكنك تثبيت، تحديث، البحث، وحذفُ الإضافات.</p><p dir="rtl">هناك العديد من الأدوات الأخرى التي تؤدّي نفس الغرض، لكن pathogen و Vundle هما الأكثر استخداماً، وسأريك كيف تستخدمهما معاً ويمكنك اختيار أي واحدة منهما، لكنّي سأعتمد فقط على Vundle في الدروس القادمة التي سأتناول فيها استعمال الإضافات المُختلفة.</p><h3 dir="rtl">1. تثبيت الإضافات باستعمال أداة pathogen</h3><p dir="rtl">أداة pathogen تعتمد مبدأ البساطة المطلقة، إذ لا تتوفر على الكثير من المهام والتعقيدات وتُمكّنك من تثبيت الإضافات بنقلها إلى مجلد:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">.vim/bundle/plugin</pre><p dir="rtl">حيثُ plugin هو ملف الإضافة التي تُريد تثبيتها.</p><p dir="rtl">لتثبيت الأداة حمّل ملفّ <a rel="external nofollow" href="https://raw.github.com/tpope/vim-pathogen/master/autoload/pathogen.vim">pathogen.vim</a> ثمّ أنقله إلى مجلّد :</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">~/.vim/autoload</pre><p dir="rtl">لديك أيضا خيار التثبيت عبر سطر الأوامر (تحتاج إلى أداة curl):</p><h4 dir="rtl">تثبيت أداة curl على Gnu/Linux</h4><p dir="rtl"><strong>على Debian وما بُني عليها:</strong></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ sudo apt-get install curl</pre><p dir="rtl"><strong>على Fedora:</strong></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ sudo yum install curl</pre><p dir="rtl"><strong>تثبيت أداة curl على Windows:</strong></p><p dir="rtl"><a rel="external nofollow" href="http://www.paehl.com/open_source/?download=curl_742_0.zip">حمّل </a><a rel="external nofollow" href="http://www.paehl.com/open_source/?download=curl_742_0.zip">curl</a>، بعد فكّ الضغط عن الملفّ انقل الملف المسمّى curl.exe إلى مجلّد %windir%</p><p dir="rtl">للوصول إلى المجلّد افتح قائمة ابدأ ثمّ تشغيل (Run) ثمّ ألصق %windir% واضغط Enter.</p><p dir="rtl">بعد الحصول على curl لأنظمة جنو/لينكس الخطوة التالية هي تطبيق الأمر التالي من الطّرفيّة (Terminal):</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ mkdir -p ~/.vim/autoload ~/.vim/bundle &amp;&amp; \
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim</pre><p dir="rtl">أما إذا كنت من مستعملي Windows فطبّق الأمر التالي في برنامج Cmd:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&gt; mkdir -p ~\vimfiles\autoload ~\vimfiles\bundle &amp;&amp; \
curl -LSso ~\vimfiles\autoload\pathogen.vim https://tpo.pe/pathogen.vim</pre><p dir="rtl">بعد نقل الملفّات وانتهاء العمليّة تحتاج إلى إضافة الأسطر التالية إلى ملفّ vimrc:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">execute pathogen#infect()
syntax on
filetype plugin indent on</pre><p dir="rtl">الآن أنت قادرٌ على تثبيت أي إضافة تريد (المثال التالي يقوم بتثبيت إضافة NERDTree على توزيعات Gnu/Linux و Mac)</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ cd ~/.vim/bundle &amp;&amp; git clone https://github.com/scrooloose/nerdtree.git
</pre><p data-pbcklang="html" data-pbcktabsize="4">أمّا إذا كنت تستعمل cmd في Windows، فهاك الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&gt; cd ~\vimfiles\bundle &amp;&amp; git clone https://github.com/scrooloose/nerdtree.git</pre><h4 dir="rtl">أداة Git</h4><p dir="rtl">معظم الإضافات مستضافة على GitHub لذلك فأداة git ضرورية للتحميل وهي متوفرة لمستخدمي جنو/لينكس على المستودعات الرّسمية ويمكنك تثبيتها تماماً كما تبّثنا أداة curl:</p><p dir="rtl">لـ Debian وما بُني عليها:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ sudo apt-get install git</pre><p dir="rtl">لـ Fedora:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ sudo yum install git</pre><p dir="rtl">لمستخدمي وندوز <a rel="external nofollow" href="http://git-scm.com/download/win">حمل </a><a rel="external nofollow" href="http://git-scm.com/download/win">git</a></p><p dir="rtl">هذا إذا أردت تثبيت الإضافات من الطرفيّة، أمّا إذا أردت أن تقوم بالأمر بشكل يدوي فهناك دائما طريقة أخرى:</p><p dir="rtl">أولاً عليك تحميل الملفّات مضغوطة:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">https://github.com/scrooloose/nerdtree/archive/master.zip</pre><p dir="rtl">حيثُ scrooloose وnerdtree تتغيّر حسب اسم الإضافة واسم المستخدم الخاص بمُطوّرها على Github.</p><p dir="rtl">فك ضغط الملفّ ثمّ انقل ما بداخله إلى مجلّد bundle.</p><h3 dir="rtl">2. تثبيت الإضافات باستعمال أداة Vundle</h3><p dir="rtl">أداة vundle شبيهة بأداة pathogen وتؤدّي نفس الغرض تقريباً، لكن أداة Vundle تستطيع فعل كثير من الأشياء التي لا تستطيع pathogen فعلها، مثلا في Vundle يُمكنك البحث عن الإضافات ، حيث تعرض لك الأداة جميع الإضافات الموافقة لما أدخلته وتعطيك إمكانية التنقّل بين نتائج البحث واختيار الإضافة المراد تثبيتها وبضغطة زر تُثبّتُ الإضافة، يُمكنك اعتبار الأداة بمثابة مدير حزم مثل apt-get في توزيعة أبنتو وyum في توزيعة فيدورا.</p><p dir="rtl">أداة Vundle تمكنّك من :</p><ul dir="rtl"><li>ضبط إعدادات الإضافات من ملفّ vimrc مباشرة.</li><li>تثبيت الإضافات.</li><li>تحديث الإضافات المثبتة.</li><li>البحث عن الإضافات المتوفّرة.</li><li>حذف الإضافات.</li><li>القيام بكلّ ما سبق باستعمال سطر أوامر بسيط وسهل.</li></ul><h4 dir="rtl">تثبيت أداة Vundle</h4><p dir="rtl">لتثبيت الأداة عليك أن تتوفر على أداة git (أنظر فصل أداة Git أعلاه)، وعليك أيضاً أن تتوفر على أداة Curl، حيثُ تُستخدم للبحث من طرف Vundle.</p><p dir="rtl">على Gnu/Linux أو ماك، طبّق الأمر التالي على الطّرفية:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">$ git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim</pre><p dir="rtl">بعد تطبيق الأمر أعلاه، أضف هذه الأسطُر إلى ملفّ vimrc:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">set nocompatible
filetype off
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'gmarik/Vundle.vim'
Plugin 'user/plugin.vim'
Plugin 'L9'
filetype plugin indent on
call vundle#end()</pre><p dir="rtl">التثبيت على نظام Windows، طبّق الأمر التالي في سطر الأوامر Cmd:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">cd %USERPROFILE% &amp;&amp; git clone https://github.com/gmarik/Vundle.vim.git vimfiles/bundle/Vundle.vim &amp;&amp; gvim _vimrc</pre><p dir="rtl">ثمّ أضف الأسطر التالية إلى ملفّ vimrc:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">set nocompatible
filetype off
set rtp+=~/vimfiles/bundle/Vundle.vim/
let path='~/vimfiles/bundle'
call vundle#begin(path)
Plugin 'gmarik/Vundle.vim'
Plugin 'user/plugin.vim'
Plugin 'L9'
filetype plugin indent on
call vundle#end()</pre><p dir="rtl">مع مراعاة أن الأسطر باللون المُختلف غير ضروريّة وهي تعني:</p><ul dir="rtl"><li><span style="font-family:courier new,courier,monospace;">Plugin 'user/plugin.vim'</span>: تثبيت إضافة من github مُباشرة حيث user هو اسم مستخدم المُطوّر و plugin.vim اسم الإضافة.</li><li><span style="font-family:courier new,courier,monospace;">Plugin 'L9'</span>: تثبيت إضافة في حال توفّرها على <a rel="external nofollow" href="http://vim-scripts.org/vim/scripts.html">Vimscripts</a>.</li></ul><p dir="rtl"><strong>ملاحظة:</strong> بعد إضافة أي سطر لتثبيت إضافة ما عليك حفظ الملفّ والخروج من vim ثمّ تطبيق الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginInstall</pre><p dir="rtl">وسيبدأ Vundle بتثبيت الإضافات واحدة تلو الأخرى.</p><p dir="rtl">الآن لتثبيت أي إضافة باستخدام Vundle يمكنك الاختيار بين الطّرق التالية:</p><h3 dir="rtl">تثبيتُ إضافة</h3><h4 dir="rtl">التثبيت من ملفّ vimrc.</h4><p dir="rtl">لقد رأينا هذه الطّريقة من قبل، فقط إضافة أحد الأسطر السّابقة أعلاه لملفّ vimrc ثمّ الخروج من Vim وفتحه مجدّدا ثمّ تنفيذ الأمر PluginInstall كفيل بالأمر.</p><h4 dir="rtl">التثبيت من المُحرّر مباشرة:</h4><p dir="rtl">Vundle يُوفّر لنا عدة أوامر جاهزة لاستخدامها داخل المُحرّر ومن بين هذه الأوامر أمر PluginInstall، ويُمكنك استعماله في المُحرّر على النّحو التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginInstall plugin</pre><p dir="rtl">حيثُ plugin هو اسم الإضافة، ويمكن أن يكون على شكل user/plugin في حال كانت الإضافة مستضافة على GitHub.</p><p dir="rtl">الأمر سيفتح تقسيما جديدا للشاشة وسيبدأ بعملية التثبيت مباشرة الوقت المُستغرق يعتمد على حجم الإضافات التي تُحاولُ تثبيتها وعلى سرعة الأنترنت لديك. عند الانتهاء يُمكنك إغلاق التقسم باستخدام:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:q</pre><p dir="rtl">أو</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:bdelete</pre><h4 dir="rtl">البحث عن إضافة</h4><p dir="rtl"><strong>عرض جميع الإضافات التي يُمكن لـ vundle تثبيتها</strong></p><p dir="rtl">إذا كنت فضولياً فمن الجيّد أن تطّلع على كميّة الإضافات الموجودة لمحرّر vim وأسمائها، لفعل ذلك نفّذ الأمر التالي على المُحرّر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginSearch!</pre><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/1.png.060067584c5e2a75de48f3b4de83a2ba.png"><img data-fileid="1899" class="ipsImage ipsImage_thumbnailed" alt="1.thumb.png.047ea7cfbb3e013ed4d98c6525a5" src="https://academy.hsoub.com/uploads/monthly_2015_05/1.thumb.png.047ea7cfbb3e013ed4d98c6525a515d6.png"></a></p><p dir="rtl">إلى حين كتابة هذا الدّرس هناك أكثر من 4000 إضافة يستطيع Vundle تثبيتها، الإضافات يُمكن أن تكون عامة ومفيدة لجميع المُبرمجين، للغة معيّنة، لبيئة ما أو حتى لإطار عمل معيّن.</p><h4 dir="rtl">تحديثُ إضافة</h4><p dir="rtl">بعد تثبيت إضافة ما أنت جاهز للعمل بها واستغلالها لتحسين أداء المُحرّر، لكن بعد مدة معيّنة سيضيف المطوّر بعض التحسينات لإضافته، وكلّنا ذاك الذي يرغبُ في الجديد المحسّن، لذلك أداة Vundle تُوفّرُ لنا أمر PluginUpdate لتحديث الإضافات.</p><p dir="rtl"><strong>لتحديث جميع الإضافات:</strong></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginUpdate</pre><p dir="rtl"><strong>لتحديث إضافة معيّنة:</strong></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginUpdate plugin</pre><p dir="rtl"><strong>لتحديث أكثر من إضافة يُمكنك فصلُ أسمائها بمسافة:</strong></p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginUpdate plugin1 plugin2</pre><p dir="rtl">يمكنكَ استخدام أمر PluginInstall مع إضافة علامة تعجّب(!) لتحديث جميع الإضافات (ليس ضروريا، مُجرّد أضف لمعلوماتك):</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginInstall!</pre><p dir="rtl">وهو أمرٌ يخبرُ Vundle بالقيام بعمليّة إعادة تثبيت، ما يجلبُ أحدث الإصدارات.</p><h4 dir="rtl">حذف إضافة</h4><p dir="rtl">قد تشعرُ أنّ الإضافة التي قُمت بتثبيتها مؤخّراً ليست مفيدة بالمرّة أو أنها تُسبب مشاكل للمحرّر، لا مشكلة يمكنك التخلّص منها باستخدام Vundle.</p><p dir="rtl">لحذف إضافة عليك أولاً أن تعرض الإضافات المُثبّتة، لقيام بذلك طبّق الأمر:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginList</pre><p dir="rtl">بعد تطبيق الأمر سيظهر قسم في الشاشة يحوي جميع الإضافات المُثبّتة تصفح باستخدام أسهم لوحة المفاتيح واختر الإضافة التي تُريد حذفها ثمّ اضغط على زرّ D.</p><p dir="rtl">ستظهر علامة – بجانب اسم الإضافة، هذا يعني أنّ الإضافة حُذفت ويمكنكَ الخروج، إذا أردت التراجع يمكنك ذلك باستخدام أمر التثبيت ما دام اسم الإضافة في ملف vimrc أو يُمكنك حذف اسمها في الملفّ إذا أردت تأكيد عدم رغبتك في رؤية وجه تلك الإضافة مُجدّدا.</p><h4 dir="rtl">حذفُ مجموعة من الإضافات دُفعة واحدة</h4><p dir="rtl">يُمكنك حذف مجموعة من الإضافات بإزالتها من ملفّ vimrc ثم تنفيذ الأمر التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginClean</pre><p dir="rtl">سيقوم Vundle بإظهار رسالة تأكيد أكتب y ثمّ Enter للتأكيد، الأمر سيقوم بحذف جميع الإضافات التي لا توجد في ملفّ vimrc.</p><h4 dir="rtl">حذفُ جميع الإضافات دُفعة واحدة (احذر!)</h4><p dir="rtl">إذا كنت تُريد أن تعود إلى زمن vim الخالص بدون أي إضافة، يُمكنك حذف جميع الإضافات بإزالتها من ملفّ vimrc ثم تنفيذ الأمر التالي:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">:PluginClean</pre><p dir="rtl">سيقوم Vundle بإظهار رسالة تأكيد أكتب y ثمّ Enter للتأكيد، الأمر سيقوم بحذف جميع الإضافات التي لا توجد في ملفّvimrc أي جميعها في حالتنا.</p><h2 dir="rtl">خاتمة</h2><p dir="rtl">تعرّفنا في هذا الدّرس على كيفيّة إدارة الإضافات ولم يبق لنا إلا شرح أهم الإضافات التي من شأنها أن تزيد من إنتاجيتك، وتُحسّن بها أداءك. الدرس القادم سيكون عن الإضافات التي يحتاج إليها كل مبرمج بغضّ النظر عن اللغة التي يتعامل بها مع برامجه وتطبيقاته.</p>
]]></description><guid isPermaLink="false">77</guid><pubDate>Sat, 09 May 2015 22:11:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x631;&#x641; &#x639;&#x644;&#x649; &#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; Vim - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x646;&#x64A;</title><link>https://academy.hsoub.com/programming/workflow/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-vim-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r76/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_05/vim.png.a0ce0b54acbc4ffa2a9a7299c1f603ec.png" /></p>

<p dir="rtl">لقد تعرّفنا معا في <a href="http://academy.hsoub.com/code/workflow/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-vim-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r71/">الدرس السابق</a> على أساسيّات التّعامل مع النّصوص والملفّات في محرر vim حيثُ شرحتُ أوامر متعلّقة بالتّعديل والحذف كالقصّ واللّصق والحذف، وتعرّفنا على مبادئ الانتقال بين الكلمات، الأسطر، التّبويبات وتقسيمات الشّاشة؛ والآن حان وقت المزيد من الأوامر -المتقدمة نسبيّا- التي ستساعدك على التعرف على المحرر بشكل أعمق.</p><h2 dir="rtl">معلومات الملف</h2><p dir="rtl">إذا قمت بفتح ملف ما وتريد معلومات عنه فكل ما عليك فعله هو الضغط على <span style="font-family:courier new,courier,monospace;">Ctrl+g</span> أو تنفيذ الأمر:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:f</pre><p dir="rtl">بعد تنفيذ الأمر ستلاحظ في أسفل الملف ستلاحظ المعلومات التالية:</p><ul dir="rtl"><li>اسم الملف</li><li>عدد أسطر الملف</li><li>إحداثيات ومكان المؤشّر في الملف</li></ul><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/1.png.c186063020e6f1d685fbbfd9da9fda58.png"><img data-fileid="1606" class="ipsImage ipsImage_thumbnailed" alt="1.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/1.thumb.png.eb4a9b61763bd62e0980d64ac111fe58.png"></a></p><h2 dir="rtl">التّعامل مع الفقرات</h2><h3 dir="rtl">1. الأزرار <span style="font-family:courier new,courier,monospace;">a, o, s | A, O, S</span> للانتقال إلى نمط الكتابة</h3><p dir="rtl">الزر <strong><span style="font-family:courier new,courier,monospace;">a</span></strong> سيقوم بالانتقال إلى وضع الكتابة بعد موضع المؤشّر مباشرة. للانتقال إلى وضع الكتابة بعد جملة كاملة أو فقرة معيّنة (بـأكملها):</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">A</pre><p dir="rtl">الزر <span style="font-family:courier new,courier,monospace;"><strong>o</strong></span> (كما ذكرنا سابقا) ينتقل بك إلى نمط الكتابة في سطر جديد (تحت المؤشّر)، أما إذا كنت ترغب بالدّخول إلى نمط الكتابة في سطر جديد فوق المؤشّر فاستعمل:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">O</pre><p dir="rtl">الزّرّ <span style="font-family:courier new,courier,monospace;"><strong>s</strong></span> سيقوم بحذف الحرف الذي يوجد فيه المؤشر وينتقل بك مباشر ة إلى وضع الكتابة، أي أن الزر <span style="font-family:courier new,courier,monospace;"><strong>s</strong></span> له دور التعديل.</p><p dir="rtl">إذا أردت تعديل جملة كاملة أو فقرة معيّنة (بـأكملها):</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">S</pre><h3 dir="rtl">2. الزرّان r و R للانتقال إلى وضع الاستبدال</h3><p dir="rtl">يوجد وضع (نمط) آخر في vim ألا وهو وضع الاستبدال (Replace) يمكنك أن تحزر فائدته من اسمه فقط، ويمكنك أيضا ملاحظة أن الزرّان المسؤولان عن الولوج إليه هما أول حرف من كلمة Replace.</p><p dir="rtl">النّمط بكل بساطة يُخوّلكَ لاستبدال ما تشاء سواء حرفا واحدا في كل مرّة أو مجموعة في آن واحد.</p><p dir="rtl">بحيث :</p><ul dir="rtl"><li>الزر <span style="font-family:courier new,courier,monospace;"><strong>r</strong></span> لاستبدال حرف واحد فقط.</li><li>الزر <span style="font-family:courier new,courier,monospace;"><strong>R</strong></span> لاستبدال عدة حروف في آن واحد.</li></ul><h3 dir="rtl">3. المزيد عن الانتقال بين الجمل والفقرات</h3><p dir="rtl">لقد ذكرنا سابقا (الدرس السابق) أساسيّات التّنقل في ملفّ معيّن، سنغطّي المزيد في هذه الفقرة.</p><p dir="rtl">الانتقال إلى الفقرة التالية، استعمل <span style="font-family:courier new,courier,monospace;"><strong>{</strong></span> .</p><p dir="rtl">تريد عكس الأمر؟ <span style="font-family:courier new,courier,monospace;">Ctrl+o</span> سيفي بالأمر.</p><h4 dir="rtl">تحريك المؤشر بين الجمل:</h4><p dir="rtl">للانتقال بين الجمل ببساطة استعمل كلا من <strong><span style="font-family:courier new,courier,monospace;">(</span></strong> و <strong><span style="font-family:courier new,courier,monospace;">)</span></strong></p><p dir="rtl">حيث <span style="font-family:courier new,courier,monospace;"><strong>)</strong></span> للانتقال إلى الجملة التالية و <strong><span style="font-family:courier new,courier,monospace;">(</span></strong> للرجوع إلى الجملة السابقة.</p><p dir="rtl">استعمل الأرقام إذا كنت ترغب بالقفز وتجاوز الجمل، مثلا <span style="font-family:courier new,courier,monospace;"><strong>3)</strong></span> للانتقال إلى الجملة الثالثة بعد المؤشر (يمكنك تغيير الرقم 3 بما تشاء).</p><h4 dir="rtl">للانتقال إلى حرف معيّن:</h4><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">fx</pre><p dir="rtl">حيث <span style="font-family:courier new,courier,monospace;"><strong>x</strong></span> هو المكان الذي نرغب بوضع مؤشر الفأرة عليه.</p><p dir="rtl">يمكنك استعمال الأرقام أيضا، مثلاً:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">3fx</pre><p dir="rtl">في هذا المثال نُخبِرُ vim بأن ينتقل إلى حرف <span style="font-family:courier new,courier,monospace;"><strong>x</strong></span> الثّالث (يعني تجاوز أوّل حرفين x وانتقل إلى الثّالث).</p><h3 dir="rtl">4. تعليم منطقة معيّنة في ملفك</h3><p dir="rtl">تخيل أنك كتبت كمّا كبيرا من الشيفرة في ملفّك، وأثناء كتابتك في لحظة معينة تذكّرت أنك تحتاج إلى إضافة شيء ما بالأعلى، لنقل بداية الملف، ستقول الأمر سهل كل ما عليّ فعله هو الضغط على <span style="font-family:courier new,courier,monospace;"><strong>gg</strong></span> للانتقال إلى الأعلى ثم أضيف ما أشاء، نعم الأمر يبدو جيّداً، لكن ماذا لو أردت العودة إلى المكان الأول الذي كنت فيه قبل الانتقال إلى الأعلى؟ هنا يأتي دور التعليم أي وضع علامة في مكان ما لتمييزه بزر معين.</p><p dir="rtl">لاستخدام التعليم قم بالضغط على <strong><span style="font-family:courier new,courier,monospace;">m</span></strong> (اختصارًا لـِ mark) ثم الزر الذي تريد التعليم به.</p><p dir="rtl"><strong>بالمثال يتضح المقال:</strong></p><p dir="rtl">إذا كان مؤشر الفأرة مثلا في منطقة ما في وسط الملف (على حرف معيّن بالضبط) وتريد تعليمه بزر <span style="font-family:courier new,courier,monospace;"><strong>a</strong></span> :</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">ma</pre><p dir="rtl">الآن انتقل إلى أي مكان ترغبه في الملف وكلما أردت العودة إلى السطر المعلّم بزر <span style="font-family:courier new,courier,monospace;"><strong>a</strong></span> ستضغط على <span style="font-family:courier new,courier,monospace;"><strong>a'</strong></span>، أما إذا كنت ترغب في العودة إلى موضع المؤشّر بالتّحديد فاضغط على <span style="font-family:courier new,courier,monospace;"><strong>a`</strong></span>.</p><p dir="rtl">يمكنك استعمال أي حرف من ( <span style="font-family:courier new,courier,monospace;">a-z A-Z</span> ) بشرط أن يكون حرفاً واحداً فقط أي أنّك تملكُ ما مجموعه 52 زرا لتعليم مختلف مناطق الملف.</p><h3 dir="rtl">5. استعمال الأرقام لتكرار العمليّات</h3><p dir="rtl">إلى الآن، تعرّفنا على استعمالات عديدة للأرقام لكن أهم ما يجب عليك معرفته بخصوص الأرقام هو أنك تستطيع أن تستعملها لتكرّر عملية ما بعدد لا نهائي من المرّات.</p><p dir="rtl">مثلا لنقل أنّ لدينا جملة في ملفنا، ننسخ الجملة باستعمال <span style="font-family:courier new,courier,monospace;"><strong>yy</strong></span> (اُنظر <a href="http://academy.hsoub.com/code/workflow/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-vim-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r71/">الدرس الأول</a>) ولكنّنا لا نريد لصقها مرة واحدة فقط بل العديد من المرات (أي تكرارها في الملف <span style="font-family:courier new,courier,monospace;"><strong>n</strong></span> مرّة). للقيام بذلك طبّق الأمر التالي:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">np</pre><p dir="rtl">بحيث <span style="font-family:courier new,courier,monospace;"><strong>n</strong></span> هو عدد المرات التي ترغب بلصق الجملة في الملف (بعد مؤشر الفأرة مباشرة).</p><p dir="rtl">أقرب مثال أستحضره حاليا هو القوائم في لغة HTML، لنقل أنّك تحتاج إلى إضافة 10 قوائم في الملف. هل تعتقد أن كتابتها بشكل يدوي سيفي بالغرض؟ (إن كان جوابك نعم فاستعدّ للتضحية بحصة لا بأس بها من وقتك الثمين). بالطبع الجواب هو لا. لذلك كل ما عليك فعله هو كتابة السطر الأول:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">&lt;li&gt; Item in The List &lt;/li&gt;</pre><p dir="rtl">ثم انسخ السطر باستعمال <span style="font-family:courier new,courier,monospace;"><strong>yy</strong></span> ثم ألصقه 10 مرّات باستعمال:</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">10p</pre><p dir="rtl" style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/2.png.03aba66a520e63410cdb5077f3336495.png"><img data-fileid="1607" class="ipsImage ipsImage_thumbnailed" alt="2.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/2.thumb.png.15bff8219ef0aee1ad42030dbbf7da02.png"></a></p><p dir="rtl">طبّقت الأمر <span style="font-family:courier new,courier,monospace;"><strong>1000000p</strong></span> وحصلت على مليون سطر (نواة لينكس؟) وملف بحجم <span style="font-family:courier new,courier,monospace;"><strong>28Mb</strong></span> ولا زال vim يستجيب في أجزاء من الثانية، لا تغيير في السرعة حتى عند الحفظ (لا أظن أن أي بيئة تطوير قادرة على فعل نفس الشّّيء خلال جزء من الثانية، وهذا سبب قويّ لاستخدام المحرر، أليس كذلك؟).</p><p dir="rtl"><strong>ملاحظة:</strong> هذا مجرد مثال والتطبيقات تكاد تكون لا نهائية لذلك الدّور عليك لتستكشف تطبيقات الطريقة وهذا الأمر متروك لخيالك ومدى رغبتك في التّعلّم .</p><h3 dir="rtl">6. التّراجع وإلغاء التراجع</h3><p dir="rtl">لقد تحدّثتُ أيضاً عن أساسيّات هذه الخاصية في الدرس السابق (<span style="font-family:courier new,courier,monospace;"><strong>u</strong></span> للتراجع عن تعديل ما و <span style="font-family:courier new,courier,monospace;">Ctrl+r</span> لإلغائِه)، وقد حان الوقت الآن لبعض العمليّات المتقدّمة.</p><p dir="rtl">تراجع عن جميع التعديلات التي قمت بها قبل <span style="font-family:courier new,courier,monospace;"><strong>x</strong></span> دقائق من الآن:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:earlier 2m</pre><p dir="rtl">هذا الأمر يقوم بالتراجع عن جميع التعديلات التي قُمت بها منذ دقيقتين، وبالطبع يمكنك استخدام الثواني كوحدة زمنية.</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:earlier 25s</pre><p dir="rtl">ولعكس العمليّة استعمل <span style="font-family:courier new,courier,monospace;"><strong>later</strong></span>:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:later 3m</pre><p dir="rtl">هذه الأوامر مفيدة إذا كنت تقوم بتعديلات عديدة في وقت قصير ولكنّك عادة لا تتذكّر الأوقات بالتّحديد، الرجوع بحسب عدد التّعديلات طريقة أفضل(نعم خاصيّة أخرى).</p><p dir="rtl">للتّراجع بحسب عدد التّعديلات:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:undo 5</pre><p dir="rtl">الأمر أعلاه يقوم بإلغاء آخر خمس تعديلات.</p><p dir="rtl">عرض قائمة التراجعات:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:undolist</pre><h2 dir="rtl">محرك البحث في vim</h2><p dir="rtl">vim يمتلكُ محركَ بحث مدهش وقوي يمكنك إعداده وتخصيصه كيفما تشاء، حيث يمكنك إخبار المحرّر بأنك تُريد أن يتجاهل حالة الأحرف (مثلا <span style="font-family:courier new,courier,monospace;"><strong>a</strong></span> و<span style="font-family:courier new,courier,monospace;"><strong>A</strong></span> كلاهما سيوافقان نتائج البحث)، ويمكنك أيضا إعداده لعرض النتائج بشكل فوري (يعني أن يقوم بالبحث بمجرد المباشرة بالكتابة).</p><p dir="rtl">إخبار المُحرّر بأننا نريد بحثا فوريا:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:set incsearch</pre><p dir="rtl">تجاهل حالة الأحرف:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:set ignorecase</pre><p dir="rtl">مثلا إذا قمت بالبحث عن “hello” :</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">/hello</pre><p dir="rtl">ستكون النتائج متوافقة مع كل من : <span style="font-family:courier new,courier,monospace;">Hello , hello , HELLO</span></p><p dir="rtl">هذه الإعدادات لن تُسجّل إذا أغلقت المحرّر، وقد ذكرت في الدّرس السّابق أنك تستطيع إضافة أسطر إلى ملف <strong><span style="font-family:courier new,courier,monospace;">vimrc.</span></strong> لكي تُسجّلَ الإعدادات بشكل افتراضي، حيث يكون كل شيء معدّا مسبقاً فور فتح المحرّر، يمكنك فعل ذلك الآن إذا كنت ترغب في ذلك. فقط افتح الملف (ملف vimrc) وألصق الأسطر التالية في الأسفل:</p><pre data-pbcklang="php" data-pbcktabsize="4" class="php ipsCode prettyprint">set incsearch
set ignorecase</pre><p dir="rtl"><strong>ملاحظة</strong>: للتنقّل بين عمليات البحث استعمل كلا من <span style="font-family:courier new,courier,monospace;"><strong>n</strong></span> و <span style="font-family:courier new,courier,monospace;"><strong>N</strong></span>.</p><h2 dir="rtl">النّصوص داخل الأقواس، علامات التّنصيص والمعقوفات</h2><p dir="rtl">vim يُوفّر مساعدةً قيّمةً للمبرمجين، حيث يحتوي على كمّ كبيرٍ من الأوامِر التي تُساعدهم على التعامل مع كتلِ التّعليمات البرمجية (code blocks)، إذ يمكّنكَ المحرّر من تعديل، حذف و نسخ كل ما يوجد بداخل الرموز مثل : <strong><span style="font-family:courier new,courier,monospace;">{} , “ “ , () , `` , &lt;&gt;</span></strong> أو حتى تضمينها كذلك.</p><h3 dir="rtl">التعديل</h3><h4 dir="rtl">1. تعديل ما بداخل الرمزين {}:</h4><p dir="rtl">يمكنك تعديل ما بداخل الرمزين <span style="font-family:courier new,courier,monospace;"><strong>{</strong></span> و <span style="font-family:courier new,courier,monospace;"><strong>}</strong></span> ببساطة وذلك باستعمال الأمر التالي:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">ci{ أو ci}</pre><p dir="rtl"><strong>ملاحظة:</strong> يجب على المؤشّر أن يكون إما على أحد الرمزين أو داخلهما (الملاحظة تنطبق على جميع الأوامر أسفله).</p><h4 dir="rtl">2. تعديل ما بداخل الرمزين &lt;&gt;:</h4><p dir="rtl">يمكن ذلك بنفس الطريقة:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">ci&lt; أو ci&gt;</pre><p dir="rtl">بنفس الطريقة يمكن تعديل ما بداخل الأقواس <span style="font-family:courier new,courier,monospace;"><strong>()</strong></span>:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">ci( أو ci)</pre><h4 dir="rtl">3. تعديل ما بداخل علامات التنصيص " أو ' أو ` :</h4><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">ci'أو ci” أو ci`</pre><h4 dir="rtl">4. تعديل ما بداخل وسوم HTML:</h4><p dir="rtl">يمكن أيضاً تعديل ما بداخل وسوم HTML بالأمر التالي:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">cit</pre><h3 dir="rtl">الحذف</h3><p dir="rtl">الحذف يكون بنفس طريقة التعديل، فقط استبدِل <span style="font-family:courier new,courier,monospace;"><strong>c</strong></span> ب <span style="font-family:courier new,courier,monospace;"><strong>d</strong></span>، مثلا لحذف ما بداخل الرمزين <span style="font-family:courier new,courier,monospace;"><strong>{}</strong></span>:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">di{ أو di}</pre><p dir="rtl">أما لحذف ما بداخل وسوم HTML:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">dit</pre><h3 dir="rtl">النسخ</h3><p dir="rtl">النسخ كذلك يتّبع نفس المنطق فقط استعمل <span style="font-family:courier new,courier,monospace;"><strong>y</strong></span> عوضا عن <span style="font-family:courier new,courier,monospace;"><strong>c</strong></span> و <span style="font-family:courier new,courier,monospace;"><strong>d</strong></span> مثلا لنسخ ما بداخل الأقواس <span style="font-family:courier new,courier,monospace;"><strong>()</strong></span>:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">yi( أو yi)</pre><p dir="rtl">في جميع الأوامر السّابقة تعلّمنا كيف ننسخ ما بالداخل فقط، فماذا لو أردنا تعديل، حذف أو نسخ العلامة أيضا؟ لفعل ذلك فقط استبدل i بـِ a، إليك مثالاً على ذلك:</p><p dir="rtl">لنقل أنّنا نملك ملفّا يحتوي على الآتي:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">if (x == 0)</pre><p dir="rtl">إذا طبّقنا الأمر(المؤشّر على أحد القوسين أو بداخلهما):</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">di)</pre><p dir="rtl">سيقوم المحرر بحذف <span style="font-family:courier new,courier,monospace;"><strong>"x == 0"</strong></span>.</p><p dir="rtl">أمّا لو طبّقنا الأمر:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">da)</pre><p dir="rtl">فسيقوم المحرّر بحذف <span style="font-family:courier new,courier,monospace;"><strong>"(x == 0)"</strong></span>.</p><p dir="rtl">وقِسْ على ذلك بقيّة الأوامر(التّعديل والنّسخ).</p><h2 dir="rtl">المسافة البادئة للنّصوص (text indent)</h2><p dir="rtl">المسافة البادئة للأسطر تعدّ من أهمّ ما يجبُ على المبرمج الاهتمام به، إذ أن الشيفرة النّقيّة تعتبر أساساً لتحديد مدى مهارة المُبرمج، وليتمكّن الآخرون من فهم ما كتبه خاصّة إذا كان يعملُ في مشروع مفتوح المصدر.</p><p dir="rtl">مثال على استعمال المسافات البادئة:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">if ...
// ...
else
// ...
end</pre><p dir="rtl">في المثال أعلاه كتبنا جملة شرطية بدون أي مسافات بادئة.</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">if ...
    // ...
else
    // ...
end</pre><p dir="rtl">أما في هذا المثال فقد قمنا بوضع مسافات بادئة لمزيد من التنسيق ولك أن تلاحظ الفرق.كما أن هناك لغات تُجبرُك على التّنسيق باستخدام المسافات البادئة (مثل Python) وإلا فلن يعمل البرنامج.</p><p dir="rtl">في vim هناك العديد من الخيارات للتحكّم بالمسافات البادئة، أولا عليك تفعيل خيار "المسافات البادئة الذكيّ" (Smart indent)، ومن المفضّل أن تضعه في ملفّ vimrc:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:set smartindent</pre><h3 dir="rtl">ضبط عرض المسافة البادئة</h3><p dir="rtl">أقصدُ بعرض المسافة البادئة، المسافة التي ستكون بين بداية السطر والكتابة (اُنظر المثال):</p><pre data-pbcklang="html" data-pbcktabsize="4" class="html ipsCode prettyprint">هذا نص بمسافة بادئة تساوي 0
 هذا نص بمسافة بادئة تساوي 1
    هذا نص بمسافة بادئة تساوي 4
          هذا نص بمسافة بادئة تساوي 10</pre><p dir="rtl">لِضبط المسافة البادئة في vim طبّق الأمر التالي:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:set shiftwidth=x</pre><p dir="rtl">حيث x عرض المسافة البادئة، من المُفضّل أن يكون 4 فقط.</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:set shiftwidth=4</pre><p dir="rtl">لوضع مسافة بادئة لسطرٍ ما استخدم:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">&gt;</pre><p dir="rtl">ولإلغاء المسافة البادئة:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">&lt;</pre><p dir="rtl">لوضع مسافة بادئة لمجموعة من الأسطُر:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">vjjj&gt;</pre><p dir="rtl">حيث <span style="font-family:courier new,courier,monospace;"><strong>v</strong></span> للولوج إلى الوضع المرئي و<strong><span style="font-family:courier new,courier,monospace;">j</span></strong> للانتقال للأسفل.</p><p dir="rtl">لوضع مسافة بادئة لما بداخل المعقوفات (<span style="font-family:courier new,courier,monospace;"><strong>{}</strong></span>)، إذا كان لديك جملة شرطيّة مثلا في لغة جافاسكريبت:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">function foo(){
//...
//...
//...
//...
}</pre><p dir="rtl">قد ترغب في وضع مسافة بادئة لجميع الأسطر التي تتواجد داخل علامتي <span style="font-family:courier new,courier,monospace;"><strong>{</strong></span> ...<span style="font-family:courier new,courier,monospace;"><strong> }</strong></span> للقيام بذلك ضع المؤشّر على إحدى العلامتين وقم بالضغط على:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">&gt;i}</pre><p dir="rtl">النتيجة ستكون كالتالي:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">function foo(){
    //...
    //...
    //...
    //...
}</pre><p dir="rtl">أمّا إذا أردت أن تنسّق الملف بكاملهِ في آن واحد فالأمر التالي سيُعطيكَ ما تريده:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">gg=G</pre><p dir="rtl">حيثُ <span style="font-family:courier new,courier,monospace;"><strong>gg</strong></span> لتحريك المؤشّر إلى أعلى الملفّ و <span style="font-family:courier new,courier,monospace;"><strong>=</strong></span> لإضافة المسافة البادئة و<span style="font-family:courier new,courier,monospace;"><strong>G</strong></span> للانتقال إلى آخر الملفّ.</p><h2 dir="rtl">تخصيص مظهر vim</h2><p dir="rtl">محرّرvim يعتمِد مبدأ البساطة، لكن هذا لا يجعله غير قابل على تخصيص مظهره، بل تستطيع أن تجعل المحرّر فخماً وذا تصميمٍ مُبتكرٍ خاصّة مع الكمّ الكبير من السمات المتاحة له، إذ أن هناك مبرمجون من مختلف أنحاء العالم ينشُرونَ سماتٍ للمُحرّر، وسنكشف بعضاً منها في هذه الفقرة.</p><h3 dir="rtl">1. تنصيب السّمات</h3><p dir="rtl">تنصيب السّمات على محرّر vim سهلٌ جدّاً، ولكنّه يختلف من نِظام تشغيل إلى آخر.</p><h4 dir="rtl">لمستخدمي Gnu/Linux أو Mac OS</h4><p dir="rtl">قُم بتحميل المِلفّات (ملفّ واحد في غالب الأحيان) ثمّ اُنقل الملفّات بامتداد vim (مثلا <span style="font-family:courier new,courier,monospace;">color.vim</span>) إلى المسار التالي :</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">~/.vim/colors/</pre><p dir="rtl"><strong>ملاحظة:</strong> علامةُ <span style="font-family:courier new,courier,monospace;"><strong>~</strong></span> اختصار يُمثّل مُجلّد المنزل الخاصّ بك.</p><p dir="rtl">إذا لم يكن مُجلّد <span style="font-family:courier new,courier,monospace;"><strong>colors</strong></span> داخل مجلّد <span style="font-family:courier new,courier,monospace;"><strong>vim.</strong></span> ( المجلّد مخفيّ افتراضياً في متصفّح الملفّات لإظهاره اضغط <span style="font-family:courier new,courier,monospace;">Ctrl+h</span>) موجوداً فقم بإنشائه. أو طبّق الأمر التالي في الطرفية (Terminal):</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">mkdir ~/.vim/colors</pre><h4 dir="rtl">لمستخدمي Windows</h4><p dir="rtl">هذا هو مسار مُجلّد<span style="font-family:courier new,courier,monospace;"><strong> vim</strong></span>. :</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">%userprofile%\vimfiles</pre><p dir="rtl">كل ما عليك فعله هو الذهاب إلى قائمة" ابدأ" (start) ثمّ " تشغيل" (run) بعد ذلك ألصق الأمر التالي:</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">%userprofile%</pre><p dir="rtl">ثمّ قم بإنشاء مجلد <span style="font-family:courier new,courier,monospace;">vimfiles</span>، وبعد ذلك أنشئ مجلّداً باسم <span style="font-family:courier new,courier,monospace;">colors</span> هذا هو المجلّد الذي سنقوم بنقل ملفات السمات داخله.</p><h3 dir="rtl">2. تفعيل السّمات والتبديل بينها</h3><p dir="rtl">الآن أنت جاهز لتفعيل السمات التي قمت بتحميلها (لا تقلق أنت لم تحمّل شيئا بعد)، بعد إكمال عمليّة نقل الملفّات المناسبة (ذات امتداد <span style="font-family:courier new,courier,monospace;">vim</span>) إلى مجلد</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">.vim/colors</pre><p dir="rtl">أو</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">%userprofile%\vimfiles\colors</pre><p dir="rtl">يمكنك مباشرة فتح vim وتجربة السّمة التي ثبّتها بالأمر:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:colorscheme theme</pre><p dir="rtl">سيتغيّر المظهر لكنّ الأمر لن يُحفَظ لحفظه ولإبقاء المظهر في كل مرة تفتح ملفّا في vim عليك إضافة السطر التالي في <span style="font-family:courier new,courier,monospace;"><strong>vimrc.</strong></span> :</p><pre data-pbcklang="javascript" data-pbcktabsize="4" class="javascript ipsCode prettyprint">colorscheme theme</pre><p dir="rtl">بالطبع مع تغيير <strong><span style="font-family:courier new,courier,monospace;">theme</span></strong> إلى اسم السّمة.</p><h3 dir="rtl">3. السّمات الافتراضيّة</h3><p dir="rtl">لنتحدّث الآن عن سمات المحرّر، في vim هناك سمات افتراضية موجودة أصلاً ولا تحتاج إلى تحميل يمكنك معاينتها وانظُر أأعجبتكَ أم تريد شيئا أفضل:</p><h4 dir="rtl">سمة desert</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/3.png.18de3af7874db16cc9fe59fe2c17e574.png"><img data-fileid="1608" class="ipsImage ipsImage_thumbnailed" alt="3.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/3.thumb.png.ebb7c34d08fd32dc00de1f4ef18a9d1c.png"></a></p><h4 dir="rtl">سمة blue</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/4.png.517ea6c0cba972b53e48016f1ebc46bd.png"><img data-fileid="1609" class="ipsImage ipsImage_thumbnailed" alt="4.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/4.thumb.png.b782f954a66195c7d895bb0c9161c934.png"></a></p><h4 dir="rtl">سمة darkblue</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/5.png.7adf806f68b71fe1d9b9ce9eb36459a3.png"><img data-fileid="1610" class="ipsImage ipsImage_thumbnailed" alt="5.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/5.thumb.png.db8b52a06c6e96fb726149288bb2fc9f.png"></a></p><h4 dir="rtl">سمة delek</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/6.png.4726030a83a889c79690e77c6b7fcd7f.png"><img data-fileid="1611" class="ipsImage ipsImage_thumbnailed" alt="6.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/6.thumb.png.1e655da03da52f5dbd34e81c7b0cf80f.png"></a></p><h4 dir="rtl">سمة elflord</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/7.png.65f14c497c29f7bfdcb2c18ca19927c4.png"><img data-fileid="1612" class="ipsImage ipsImage_thumbnailed" alt="7.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/7.thumb.png.208410d9accf6fe5badf8e21c49d7f7d.png"></a></p><h4 dir="rtl">سمة morning</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/8.png.5671bc39fcc135241cca018d363bf4ae.png"><img data-fileid="1613" class="ipsImage ipsImage_thumbnailed" alt="8.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/8.thumb.png.b0f631b8a300e62d943cc3aff24fbc5a.png"></a></p><h4 dir="rtl">سمة pablo</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/9.png.8b26cf6212dd993daa561183ab11b5bb.png"><img data-fileid="1614" class="ipsImage ipsImage_thumbnailed" alt="9.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/9.thumb.png.daef602c755a0c7011da81d51a7d2286.png"></a></p><h4 dir="rtl">سمة slate</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/10.png.2ecc5ad0bb75cd1dd7a47003b85498c0.png"><img data-fileid="1615" class="ipsImage ipsImage_thumbnailed" alt="10.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/10.thumb.png.3622bdd2a132bd43c6a0590580274e14.png"></a></p><p dir="rtl">هناك المزيد والمزيد من السّمات التي يُوفّرها لك المحرّر يمكنك تصفحها عبر الأمر:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:colorscheme &lt;tab&gt;</pre><h3 dir="rtl">تحميل السّمات</h3><p dir="rtl">إن لم يُعجبك أي مظهر من مظاهر المحرّر الموجودة أعلاه، لا تقلق لا يزال هناك أمل، سأسرد لك بعضا من السّمات الموجودة خارج المحرّر وعليك تحميلها إذا أردت تفعيلها.</p><p dir="rtl">وكما قلت سابقا لتفعيل أيّ سمة يكفي أن تنقل الملفّ بامتداد <span style="font-family:courier new,courier,monospace;">vim</span> إلى مجلّد <span style="font-family:courier new,courier,monospace;"><strong>colors</strong></span> ثم نفّذ الأمر:</p><pre data-pbcklang="css" data-pbcktabsize="4" class="css ipsCode prettyprint">:colorscheme theme</pre><p dir="rtl">حيثُ <span style="font-family:courier new,courier,monospace;">theme</span> هو اسم الملف، مثلا إذا كان اسم الملفّ <span style="line-height: 22.3999996185303px;"><span style="font-family:courier new,courier,monospace;">color.vim</span> </span>فيكفي أن تغيّر <span style="font-family:courier new,courier,monospace;"><strong>theme</strong></span> إلى <strong><span style="font-family:courier new,courier,monospace;">color</span></strong>، ولإبقاء السّمة، أضف السّطر إلى ملفّ <span style="font-family:courier new,courier,monospace;"><strong>vimrc.</strong></span>.</p><h4 dir="rtl">سمة Guardian</h4><p dir="rtl">هذه أحد السمات التي <a href="http://www.vim.org/scripts/download_script.php?src_id=4128" rel="external nofollow">يمكن تحميلها</a> مثلا، ثم تنصيبها بالطريقة التي قمنا بشرحها أعلاه:</p><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/11.png.6a361e8f4f37813ff6313ab310c9a6f1.png"><img data-fileid="1616" class="ipsImage ipsImage_thumbnailed" alt="11.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/11.thumb.png.9eb586644d24687b3a81a3b754066b56.png"></a></p><h4 dir="rtl">سمة Github</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/12.png.f6708ae841db5b36127266527d755388.png"><img data-fileid="1617" class="ipsImage ipsImage_thumbnailed" alt="12.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/12.thumb.png.1b08d2a83aa8994bfd20a120b47a822c.png"></a></p><p dir="rtl">هذه سمةٌ أخرى <a href="http://www.vim.org/scripts/download_script.php?src_id=23147" rel="external nofollow">يُمكن تحميلها</a> شبيهة بسمة موقع Github.</p><h4 dir="rtl">سمة Vividchalk</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/13.png.c070757dc4030883059fe8aae52f231e.png"><img data-fileid="1618" class="ipsImage ipsImage_thumbnailed" alt="13.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/13.thumb.png.23738cd108802d40cd1cdf040fb1e638.png"></a></p><p><a href="https://raw.githubusercontent.com/tpope/vim-vividchalk/master/colors/vividchalk.vim" rel="external nofollow">لتحميل السمة</a>.</p><h4 dir="rtl">سمة Candy</h4><p style="text-align: center;"><a class="ipsAttachLink ipsAttachLink_image" rel="external nofollow" href="https://academy.hsoub.com/uploads/monthly_2015_05/14.png.e1d236ae3a5353591b67fc39551c745e.png"><img data-fileid="1619" class="ipsImage ipsImage_thumbnailed" alt="14.png" src="https://academy.hsoub.com/uploads/monthly_2015_05/14.thumb.png.993ef0d21a7efcb988860ef34568a432.png"></a></p><p dir="rtl"><a rel="external nofollow" href="http://www.vim.org/scripts/download_script.php?src_id=817">تحميل السّمة</a></p><h2 dir="rtl">ختاما</h2><p dir="rtl">لقد تعرّفنا في هذا الدرس على قدراتِ vim المتقدّمة في التّحرير والتّعامل مع مختلف أنواع النّصوص والجمل، وأيضاً على طرق لتخصيص المحرّر، ولكنّه يحوي أكثر من هذا كلّه خاصّة أنّه مليء بالمفاجآت، والإضافات التي تستطيع أن تجعله أكثر من مجرّد محرّر!</p>
]]></description><guid isPermaLink="false">76</guid><pubDate>Fri, 01 May 2015 11:08:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x631;&#x641; &#x639;&#x644;&#x649; &#x623;&#x633;&#x627;&#x633;&#x64A;&#x627;&#x62A; Vim - &#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x623;&#x648;&#x644;</title><link>https://academy.hsoub.com/programming/workflow/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-vim-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r71/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_04/vim.png.a663b517bd1e648e4fd44b95391f3ad9.png" /></p>

<p dir="rtl">
	الأدوات التي تُساعد المُبرمج في عمله كثيرة ومتعددّة، وهي التي تكون سببا إما في زيّادة أو تقليص إنتاجيته وسرعة عمله، لذلك فمن المهم اختيّار الأدوات بعناية، والمحرر أهم هذه الأدوات، إذ به تنجز معظم عملك البرمجي ولا يمكن لأيّ مبرمج العيش بدون محرّر. في هذا المقال سنطّلع معا على محرّر Vim الذي يعتبر من أشهر المحررات والذي يستخدمه عدد كبير من المبرمجين من مختلف أنحاء العالم في تعاملهم مع لغات البرمجة المختلفة؛ قد تصدمك حقيقة أن vim أُطلق منذ أكثر من 23 عاما، ولكنه لم يَشِخ بعد، فمُجتمَعُهُ لا زال يكبر يوما بعد يوم، ومعظم المبرمجين المعروفين يستخدمونه ويعتمدون عليه في تحرير شِفراتهم.
</p>

<h2 dir="rtl">
	تَعَلُّمُ كيفية التّعامُلِ مع محرّر نصوص؟
</h2>

<p dir="rtl">
	نعم لا حرج في ذلك، في الحقيقة عندما تستعمل شيئا ما لساعات طِوال لا بد أن تتعلّم كيف تكون أسرع في إنجاز العمل، ولذلك فإن تعلّم محرّر vim يستحق منك أن تعطيه شيئا من وقتك! ففي النهاية النّتائج هي المهمّة وما تريد أن تصل إليه هو التّعامل مع الملفات البرمجية بشكل أسرع وأكثر إنتاجية.
</p>

<h2 dir="rtl">
	لماذا vim ؟
</h2>

<p dir="rtl">
	معظم الذين يجربون هذا المحرر لأول مرة سرعان ما ينعتونه ب “محرّر من العصر الحجري” خاصة بواجهته التي قد تبدو للوهلة الأولى “سيّئة”، والكثير ممّن لا يعرفونه جيّدا يقولون أنه لا يستحق أن يسمى محرّرا إمّا لصعوبة أوامره أو لأسباب أخرى عادة ما تكون مبنية على قلّة المعرفة، فالأوامر ليست صعبة وتستحقّ منك تعلّمها بكلّ تأكيد.
</p>

<p dir="rtl">
	لقد وقعتُ في هذا الفخ لكنّني سرعان ما سحبت كلامي بعد أن علمت أنّه من المحرّرات الأكثر استعمالا من طرف المبرمجين، مُدراء الخواديم،  بل ويستخدمه عدد لا بأس به من الكتّاب (بالّلغة الإنجليزيّة) للتّدوين في مدوناتهم أو كتابة مقالات وغير ذلك، ولا أظنّني أملك مخزونا كافيّا من الكلمات لوصفه فهو في النّهاية المحرّر الغامض الذي ستتعلّم المزيد عنه كل يوم.
</p>

<p dir="rtl">
	معظم الذين يقولون أن المحرّر سيّء لم يجرّبوه في الأساس أو أنّهم لم يدرسوه بشكل جدي، الشّيء الذي ستتفاداه أنت بعد قراءتك لهذا الدّرس. وإليك بعضا من الأسباب التي قد تدفعك إلى تعلّمه
</p>

<h3 dir="rtl">
	1. لأنّه ممتع
</h3>

<p dir="rtl">
	أهمّ الأساب التي قد تدفعك لتعلّم vim هو المتعة التي ترافقك أثناء كتابة شيفراتك البرمجية وتعديلها، عند تعَوّدِكَ على إستعمال المحرر ستصل إلى مرحلة يكون فيها التحرير كلعبة بين يديك.
</p>

<h3 dir="rtl">
	2. لأن الكثير من المبرمجين يستعملونه
</h3>

<p dir="rtl">
	محرر vim ليس مجرد محررًا بسيطًا، بل هو محرر ذو قدرات عالية وخير دليل على ذلك هو العدد الكبير من المبرمجين الذين يستعملونه، إذ في<a href="http://www.sitepoint.com/editor-rubyists-use/" rel="external nofollow"> أحد الإحصائيات</a> فإن أكثر من نصف مبرمجي لغة Ruby وهي لغة كائنية <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr> يستعملون vim وحوالي <a href="http://www.sitepoint.com/which-code-editors-do-pythonists-use/" rel="external nofollow">الثلث</a> من مبرمجي Python أيضا يستعملون Vim.
</p>

<p dir="rtl">
	الإحصائيتان شملتا عددا من مبرمجي لغتي Ruby وPython فقط وهما لغتان رغم شهرتها إلا أنهما تبقيان أقل شهرة من لغات كـ ++C ، C  وJavascript وغيرهم، فما بالك بعدد المستخدمين من المبرمجين باللغات الأخرى.
</p>

<h3 dir="rtl">
	3. لأنّه قابل للتّخصيص
</h3>

<p dir="rtl">
	يمكنك تخصيص vim إلى درجة كبيرة حيث يمكنك تغيير الأوامر أو إضافة أخرى جديدة بالإضافة إلى كمية الإضافات الهائلة المتاحة له والتي تجعله قادرا على تنفيذ مهام ووظائف جديدة تُبرمج هذه الإضافات بلغة خاصة تسمى فيمسكريبت vimscript كما يدعم برمجة الإضافات بلغات أخرى مثل (python ; ruby ; tcl ; lua ..)
</p>

<p dir="rtl">
	الخلاصة هنا أن محرر Vim يتمتع بالشهرة والكفاءة وقابلية الإستخدام التي ستدفعك إلى تجربته وتعلّم التّعامل معه ففي النهاية إتقان مهارة جديدة أمر يصقل خبرات المبرمج.
</p>

<h2 dir="rtl">
	تنصيب المحرر
</h2>

<p dir="rtl">
	لتنصيبه على توزيعات جنو/لينكس المبنية على الدبيان (Ubuntu ،Linux Mint ،Elementary OS...)، طبّق هذا الأمر في الطرفية Terminal:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">$ sudo apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install vim</span></pre>

<p dir="rtl">
	لتنصيبه على توزيعة فيدورا، طبق هذا الأمر في الطرفية Terminal:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">$ sudo yum install vim</span></pre>

<p>
	لتنصيبه على Windows، يمكنك <a href="http://www.vim.org/download.php#pc" rel="external nofollow">تحميل Gvim</a>، ولتنصيبه على Mac فإن Vim يأتي مثبتا مُسبقا على أنظمة الماك، لذلك كل ما عليك فعله هو كتابة vim في الطرفية Terminal لتشغيله.
</p>

<h2 dir="rtl">
	أهم الأوامر قبل فتح ملفّ
</h2>

<p dir="rtl">
	يمكنك فتح أي ملف تريده من الطّرفية Terminal بكتابة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">vim file</span><span class="pun">.</span><span class="pln">txt</span></pre>

<p dir="rtl">
	غيّر <span style="font-family:courier new,courier,monospace;">file.txt</span> إلى الملف الذي ترغب في فتحه إن لم يكن موجودا فسيُنشئ vim ملفا بذلك الإسم.
</p>

<p dir="rtl">
	<strong>ملاحظة</strong>: إذا كنت على لينكس أو Mac فتأكّد من أنك على المجلد الصحيح بإستخدام أمر <span style="font-family:courier new,courier,monospace;">pwd</span> ويمكنك إستخدام أمر <span style="font-family:courier new,courier,monospace;">ls</span> لعرض الملفات المتاحة كما تستطيع التنقل بين المجلدات بإستخدام:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">cd directory</span></pre>

<p dir="rtl">
	مع تغيير directory إلى إسم المجلّد وللرّجوع إستخدم:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">cd </span><span class="pun">..</span></pre>

<p dir="rtl">
	وللرّجوع إلى مجلّد المنزل قم بإدخال أمر <span style="font-family:courier new,courier,monospace;">cd</span> فقط
</p>

<p dir="rtl">
	أول ما ستقوم به عند فتح vim هو الضغط على زر <em> وهو الذي سيمكنك من الدخول إلى نمط الكتابة ويمكنك كتابة ماتشاء في الملف.</em>
</p>

<ul>
<li>
		<span style="font-family:courier new,courier,monospace;"><strong>[ i]</strong></span> للدخول إلى نمط الكتابة إضغط على.
	</li>
	<li>
		<strong><span style="font-family:courier new,courier,monospace;">[o]</span></strong>  للدخول إلى نمط الكتابة في سطر جديد.
	</li>
	<li>
		<span style="font-family:courier new,courier,monospace;"><strong>[Esc]</strong></span> للخروج من نمط الكتابة إلى نمط الأوامر.
	</li>
	<li>
		<span style="font-family:courier new,courier,monospace;"><strong>[v]</strong></span> للدخول إلى النمط المرئي ومنه يمكنك تحديد نص أو مجموعة كلمات.
	</li>
</ul>
<h2 dir="rtl">
	أنماط (أوضاع) Vim
</h2>

<h3 dir="rtl">
	نمط الكتابة Insert mode
</h3>

<p dir="rtl">
	نمط الكتابة يمَكّنكَ من كتابة وتعديل ما تشاء. وهو النمط الأساسي (الجزء الذي لا يحتاج إلى تعلّمه).
</p>

<p dir="rtl" style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_04/1.png.77d01073456f0480465c7a560a6d768d.png" rel="" data-fileid="1518"><img class="ipsImage ipsImage_thumbnailed" data-fileid="1518" src="https://academy.hsoub.com/uploads/monthly_2015_04/1.thumb.png.66f57839a366be79f4df7aa15ac52c5c.png" alt="1.png"></a>
</p>

<h3 dir="rtl">
	النمط المرئي Visual mode
</h3>

<p dir="rtl" style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_04/2.png.3ceb33392c5806f5e98e86c3213185a6.png" rel="" data-fileid="1519"><img class="ipsImage ipsImage_thumbnailed" data-fileid="1519" src="https://academy.hsoub.com/uploads/monthly_2015_04/2.thumb.png.45b5df5b1b02df00710ea81d91fccd43.png" alt="2.png"></a>
</p>

<p dir="rtl">
	في النمط المرئي يمكنك تحديد النصوص والكلمات بإستعمال طُرق الإنتقال (التي سنذكرها لاحقا)، وتطبيق الأوامر عليها سواء حذفها أو نسخها أو تعديلها...
</p>

<h3 dir="rtl">
	نمط الأوامر Command mode
</h3>

<p dir="rtl">
	نمط الأوامر هو النّمط الذي يخوّل لك إعطاء الأوامر للمحرر, سواء كان حذف كلمة أو حذف جملة أو تغيير شيء ما أو أي شيء من هذا القبيل وهو النمط الإفتراضي.
</p>

<h2 dir="rtl">
	أوامر Vim
</h2>

<p dir="rtl">
	فتح ملف بإسمه (إذا كان موجودا في نفس المجلد):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">e file</span><span class="pun">.</span><span class="pln">txt</span></pre>

<p dir="rtl">
	إذا كان في مجلد آخر:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">e directory</span><span class="pun">/</span><span class="pln">file</span><span class="pun">.</span><span class="pln">txt</span></pre>

<p>
	إذا أردت تصفح الملفات الموجودة وإختيّار ملف:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">e </span><span class="pun">.</span></pre>

<p>
	للحفظ تحت إسم آخر:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">w </span><span class="pun">إسم</span><span class="pln">_</span><span class="pun">الملف</span></pre>

<p>
	حفظ الملف:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">w</span></pre>

<p dir="rtl">
	الحفظ والمغادرة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">wq</span></pre>

<p dir="rtl">
	المغادرة بدون حفظ:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">q</span><span class="pun">!</span></pre>

<h3>
	إستعمال أوامر النظام داخل vim
</h3>

<p dir="rtl">
	يمكنك إستعمال أوامر النظام في vim كالتالي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:!</span><span class="pln"> cmnd</span></pre>

<p dir="rtl">
	مثلا لنقل أنك تعمل على صفحة Html وتريد عرضها بمتصفح فايرفوكس، كل ما عليك فعله هو:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:!</span><span class="pln"> firefox index</span><span class="pun">.</span><span class="pln">html</span></pre>

<p>
	يمكنك الإنتقال بين الأحرف باستخدام الأسهم على لوحة المفاتيح أو يمكنك استعمال الأحرف:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">k </span><span class="pun">أعلى</span><span class="pln">

j </span><span class="pun">أسفل</span><span class="pln">

h </span><span class="pun">يسار</span><span class="pln">

l </span><span class="pun">يمين</span></pre>

<p dir="rtl">
	تستطيع القفز من مكان إلى آخر بإضافة عدد الأحرف أو الأسطر المراد تجاوزها قبل كل سهم، مثلا إذا أردت الإنتقال 20 حرفا إلى اليمين:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="lit">20l</span></pre>

<p dir="rtl">
	الإنتقال 35 سطرا إلى الأسفل:
</p>

<pre class="html ipsCode prettyprint prettyprinted" data-pbcklang="html" data-pbcktabsize="4" style="">
<span class="lit">35j</span></pre>

<p dir="rtl">
	الإنتقال إلى بداية الملف:
</p>

<pre class="html ipsCode prettyprint prettyprinted" data-pbcklang="html" data-pbcktabsize="4" style="">
<span class="pln">gg</span></pre>

<p dir="rtl">
	الإنتقال إلى نهاية الملف:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">G</span></pre>

<p dir="rtl">
	الإنتقال إلى بداية السطر:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="lit">0</span></pre>

<p dir="rtl">
	الإنتقال إلى نهاية السطر:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">$</span></pre>

<p dir="rtl">
	الإنتقال إلى سطر معين (السطر 15 في هذا المثال):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="lit">15gg</span></pre>

<p dir="rtl">
	للتراجع عن تعديل:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">u</span></pre>

<p dir="rtl">
	للتراجع عن التراجع:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="typ">Ctrl</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> r</span></pre>

<p dir="rtl">
	نسخ سطر:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">yy</span></pre>

<p dir="rtl">
	حذف سطر:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">dd</span></pre>

<p dir="rtl">
	نسخ، حذف عدد من الأسطر (4 في هذا المثال):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="lit">4dd</span><span class="pln">
</span><span class="lit">4yy</span></pre>

<p dir="rtl">
	حذف كلمة (ضع المؤشر على أول الكلمة):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">dw
yw </span><span class="pun">للنسخ</span></pre>

<p dir="rtl">
	للقص يمكنك إستبدال <span style="font-family:courier new,courier,monospace;"><strong>d</strong></span> و <span style="font-family:courier new,courier,monospace;"><strong>y</strong></span> بـِ <span style="font-family:courier new,courier,monospace;"><strong>x</strong></span>
</p>

<p dir="rtl">
	للصق الجزء المنسوخ أو المقصوص:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">p</span></pre>

<p dir="rtl">
	لتحديد جزء من النّص:
</p>

<p dir="rtl">
	أدخل إلى النمط المرئي بإستعمال <span style="font-family:courier new,courier,monospace;">Ctrl + v </span>ثم إنتقل بإستخدام الأحرف <strong><span style="font-family:courier new,courier,monospace;">hjkl</span></strong> أو الأسهم لتحديد ما تريد.
</p>

<p dir="rtl">
	التعامل مع النص المحدد:
</p>

<p dir="rtl">
	للتعامل مع النص المحدد يمكنك ببساطة إستعمال الأحرف <span style="font-family:courier new,courier,monospace;"><strong>y</strong></span> للنسخ و <span style="font-family:courier new,courier,monospace;"><strong>d</strong></span> للحذف و <span style="font-family:courier new,courier,monospace;"><strong>x</strong></span> للقص.
</p>

<p>
	وللبحث عن نص ما:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">/</span><span class="typ">Search_query</span></pre>

<p dir="rtl">
	إستبدل <span style="font-family:courier new,courier,monospace;">Search_query</span> بما تبحث عنه.
</p>

<p dir="rtl">
	التعامل مع عدة ملفات في آن واحد:
</p>

<p>
	يمكنك تقسيم الشاشة إلى ما تشاء من الأجزاء والتعامل مع الملفات - الأمر أشبه بالنوافذ المبوبة tabs (الموجودة كذلك في vim).
</p>

<p dir="rtl">
	لتقسيم الشاشة أفقيا :
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">sp</span></pre>

<p dir="rtl">
	عموديا :
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">vs</span></pre>

<p dir="rtl">
	للتّنقل بين أقسام الشاشة :
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="typ">Ctrl</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> ww</span></pre>

<p dir="rtl">
	أو:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="typ">Ctrl</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> w </span><span class="pun">+</span><span class="pln"> </span><span class="pun">الأسهم</span></pre>

<h3 dir="rtl">
	التّبويبات Tabs
</h3>

<p dir="rtl">
	لفتح عدّة ملفات كل ملف في تبويبة يمكنك تنفيذ الأمر التالي (في الطّرفيّة Terminal):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">$ vim </span><span class="pun">-</span><span class="pln">p file1 file2 file3</span></pre>

<p dir="rtl">
	إنشاء نافذة جديدة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabnew</span></pre>

<p dir="rtl">
	إغلاقها:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabc</span></pre>

<p dir="rtl">
	الإنتقال إلى التّبويبة التالية:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabn </span><span class="pun">(</span><span class="pln">n </span><span class="pun">إختصارا</span><span class="pln"> </span><span class="pun">ل</span><span class="pln"> </span><span class="kwd">next</span><span class="pun">)</span></pre>

<p dir="rtl">
	الإنتقال إلى التّبويبة السابقة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabp </span><span class="pun">(</span><span class="pln">p </span><span class="pun">إختصار</span><span class="pln"> </span><span class="pun">ل</span><span class="pln"> previous</span><span class="pun">)</span></pre>

<p dir="rtl">
	يمكن إستعمال الأرقام فمثلا للقفز إلى التّبويبة الثالثة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabn3</span></pre>

<p dir="rtl">
	الذهاب إلى التّبويبة الأخيرة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabl</span></pre>

<p dir="rtl">
	الرجوع إلى التّبويبة الأولى:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabr</span></pre>

<p>
	 
</p>

<p dir="rtl">
	لعرض التّبويبات:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="pln">tabs</span></pre>

<p dir="rtl">
	التّعامل مع التّبويبات هكذا أمر متعب أليس كذلك ؟
</p>

<p>
	كل ما عليك فعله هو إنشاء إختصارات لها وهذا سكريبت جاهز يقوم بالأمر:
</p>

<p dir="rtl">
	فقط أضف الأسطر إلى ملف <strong><span style="font-family:courier new,courier,monospace;">vimrc.</span></strong> الموجود في مجلّد المنزل <span style="font-family:courier new,courier,monospace;">HOME$</span> (ربما قد لا يكون موجودا، عليك إنشاءه إن لم يكن موجودا):
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">map </span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">-</span><span class="pln">t</span><span class="pun">&gt;&lt;</span><span class="pln">up</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln">tabr</span><span class="str">&lt;cr&gt;</span><span class="pln">
map </span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">-</span><span class="pln">t</span><span class="pun">&gt;&lt;</span><span class="pln">down</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln">tabl</span><span class="str">&lt;cr&gt;</span><span class="pln">
map </span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">-</span><span class="pln">t</span><span class="pun">&gt;&lt;</span><span class="pln">left</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln">tabp</span><span class="str">&lt;cr&gt;</span><span class="pln">
map </span><span class="pun">&lt;</span><span class="pln">C</span><span class="pun">-</span><span class="pln">t</span><span class="pun">&gt;&lt;</span><span class="pln">right</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln">tabn</span><span class="str">&lt;cr&gt;</span></pre>

<p>
	<strong>ملاحظة:</strong> بما أن الملف يبدأ بنقطة فهو مخفي، إذا حاولت رؤيته من متصفح ملفات فعليك أن تظهر الملفات المخفية (<span style="font-family:courier new,courier,monospace;">Ctrl+h</span>).
</p>

<p dir="rtl">
	<strong>ملاحظة لمستخدمي Windows</strong>، للحصول على ملف vimrc عليك القيام بالتالي:
</p>

<p dir="rtl">
	افتح قائمة ابدأ (start) ثمّ "تشغيل" (run) بعد ذلك ألصق الأمر التالي:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">%</span><span class="pln">userprofile</span><span class="pun">%</span></pre>

<p dir="rtl">
	ثمّ قم بإنشاء ملفّ باسم:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pln">_vimrc</span></pre>

<p dir="rtl">
	الإختصارات الآن هي كالتالي :
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="typ">Ctrl</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> t </span><span class="pun">+</span><span class="pln"> </span><span class="pun">الأسهم</span></pre>

<p dir="rtl">
	الأعلى والأسفل للتنقل بين التبويبة الأولى والأخيرة على التوالي، وأما الأسهم يمين ،يسار فهي للتنقل بين التبويبات بشكل عادي (التالية ، السابقة).
</p>

<h3 dir="rtl">
	بعض الأسطر التي قد تَوَدُّ إضافتها لملف vimrc.
</h3>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="kwd">set</span><span class="pln"> encoding</span><span class="pun">=</span><span class="pln">utf</span><span class="pun">-</span><span class="lit">8</span><span class="pln">
</span><span class="kwd">set</span><span class="pln"> number
</span><span class="kwd">set</span><span class="pln"> hlsearch
</span><span class="kwd">set</span><span class="pln"> hlsearch </span><span class="pun">لتضليل</span><span class="pln"> </span><span class="pun">النص</span><span class="pln"> </span><span class="pun">الذي</span><span class="pln"> </span><span class="pun">تبحث</span><span class="pln"> </span><span class="pun">عنه</span><span class="pln">
</span><span class="kwd">set</span><span class="pln"> number </span><span class="pun">لإضافة</span><span class="pln"> </span><span class="pun">الأرقام</span><span class="pln"> </span><span class="pun">في</span><span class="pln"> </span><span class="pun">الجانب</span></pre>

<p>
	<strong>ملاحظة:</strong> يمكنك إظهار الترقيم فقط بكتابة:
</p>

<pre class="php ipsCode prettyprint prettyprinted" data-pbcklang="php" data-pbcktabsize="4" style="">
<span class="pun">:</span><span class="kwd">set</span><span class="pln"> number</span></pre>

<p dir="rtl">
	وهذه صورة للمحرر بعد إضافة setnumber إلى ملف vimrc:
</p>

<p dir="rtl" style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2015_04/3.png.b24dcc1bd8c5733d0c7117f1f29b5b46.png" rel="" data-fileid="1520"><img class="ipsImage ipsImage_thumbnailed" data-fileid="1520" src="https://academy.hsoub.com/uploads/monthly_2015_04/3.thumb.png.23f41fc6952a6390300b13d96918236c.png" alt="3.png"></a>
</p>

<h2 dir="rtl">
	خاتمة
</h2>

<p dir="rtl">
	vim يمتلك العديد من الأوامر والمميزات، العديد منها بحيث لا يستطيع مقال واحد شرحها، لذلك فهذا المقال مجرد مدخل إلى عالم محرر Vim و أنصحك بقراءة المزيد عنه إذا كنت مهتما، سنتعرف في <a href="https://academy.hsoub.com/programming/workflow/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-vim-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r76/" rel="">الجزء الثاني من أساسيات Vim</a> عن معلومات إضافية عن هذا المحرر وكيفية تطويعه لمتطلباتك اليومية.
</p>

<p><a href="https://academy.hsoub.com/uploads/monthly_2015_04/figure-1.png.2c32a679f0a2d74a3f8aa25e929628af.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="1506" src="https://academy.hsoub.com/uploads/monthly_2015_04/figure-1.thumb.png.bdb6818aedfa53523878ad3228f30890.png" class="ipsImage ipsImage_thumbnailed" alt="figure-1.png"></a></p>
<p><a href="https://academy.hsoub.com/uploads/monthly_2015_04/figure-3.png.eae550176a0153251bbb7d91637c8948.png" class="ipsAttachLink ipsAttachLink_image"><img data-fileid="1508" src="https://academy.hsoub.com/uploads/monthly_2015_04/figure-3.thumb.png.8acbe87016bcaa9e2a5f07264f7a95e2.png" class="ipsImage ipsImage_thumbnailed" alt="figure-3.png"></a></p>]]></description><guid isPermaLink="false">71</guid><pubDate>Tue, 28 Apr 2015 12:48:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x647;&#x648; Bower&#x61F;</title><link>https://academy.hsoub.com/programming/workflow/%D9%85%D8%A7-%D9%87%D9%88-bower%D8%9F-r15/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2015_03/bower.png.25abac4eb0d13f8809d12028b1cc3072.png" /></p>
<p>تتألّف صفحات الويب التي نراها على المتصفح من مكوِّنات متعددة؛ كأطر العمل والمكتبات وملفات JavaScript وCSS وغيرها.</p><p>‏<a rel="external nofollow" href="http://bower.io">Bower‏</a> أداة لإدارة هذه المكوِّنات (أو الحزم) المُخصّصة للويب، كالتثبيت والتحديث والحذف وغيرها من عمليات الإدارة.</p><p>يشبه Bower إلى حد كبير الأدوات المخصّصة لإدارة الحزم في لغات برمجة آخرى، مثل gem للغة Ruby وComposer لـPHP وnpm لـNode.js.</p><h2>لكن ما الفائدة منه؟ ألا يمكنني متابعة عملي كما اعتدت من دونه؟</h2><p>يمكننا الاستفادة من أداة Bower في عدّة أمور، فلنفرض أن مشروعك القادم يحتاج إلى استخدام مكتبة <a rel="external nofollow" href="http://jquery.com">jQuery‏</a> وإطار عمل <a rel="external nofollow" href="http://getbootstrap.com">Twitter Bootstrap‏</a> وخطّ الأيقونات <a rel="external nofollow" href="http://fortawesome.github.io/Font-Awesome">Font Awesome‏</a>.</p><p>لتنزيل كل واحدة من المُتطلّبات يقوم المطور بما يلي:</p><ul><li>الذهاب إلى موقع المكتبة أو إطار العمل</li><li>التوجه إلى زرّ التحميل</li><li>تحميل الملف المضغوط</li><li>فك ضغط الملف المضغوط في مجلد المشروع</li></ul><p>لو كان المشروع يحتاج إلى 3 أدوات فقط سيقوم المطور بتكرار الخطوات السابقة 3 مرات، ولو كان يحتاج 10 أدوات سيقوم بتكرار الخطوات ذاتها 10 مرات! هل ترى حجم العمل المطلوب فقط لتحميل المُتطلّبات؟</p><p>دعنا نرَ كيف يمكن ﻷداة Bower أن تساعدنا في اختصار الوقت. بعد تثبيت الأداة على الحاسوب، يمكن تنزيل جميع ما سبق باستخدام الأمر التالي:</p><pre class="php ipsCode prettyprint">bower install jquery bootstrap fontawesome</pre><p>هذا كل ما في الأمر. بهذا نكون قمنا بتثبيت المُتطلّبات الثلاثة معاً، ويمكن البدء باستخدامها دون هدر وقت بتكرار الخطوات التقليدية. ومهما ازداد عدد المُتطلّبات يبقى تثبيتها بهذه الطريقة البسيطة نفسها.</p><p>من ميزات هذه الأداة تحديد الإصدار المطلوب للمكوِّنات (سواء كانت مكتبات أو أطر العمل). إن كنتَ تريد مثلاً الإصدار رقم 3.1.1 من إطار عمل Twitter Bootstrap فيمكن أن تحدد هذا في أمر التثبيت نفسه، أما بالطريقة التقليدية فتحتاج إلى البحث هنا وهناك لتجد مبتغاك!</p><p><em>ملاحظة: سنأتي لطريقة الاستخدام بالتفصيل، الأمثلة السابقة فقط لتوضيح الفوائد والميزات التي يقدمها Bower.</em></p><h2>من يستخدم Bower؟</h2><p>الكثير من أطر العمل والمكتبات تستخدم Bower، على سبيل المثال:</p><ul><li>‏<a rel="external nofollow" href="http://getbootstrap.com">Twitter Bootstrap‏</a> إطار العمل الشهير، مخصّص لإنشاء الواجهات وعناصر الويب.</li><li>‏<a rel="external nofollow" href="http://foundation.zurb.com/">Foundation‏</a> إطار عمل شبيه بـTwitter Bootstrap.</li><li>‏<a rel="external nofollow" href="http://jquery.com">jQuery‏</a> مكتبة JavaScript الشهيرة.</li><li>‏<a rel="external nofollow" href="http://angularjs.org/">Angular JS‏</a> مكتبة JavaScript لإنشاء تطبيقات وحيدة الصفحة (single-page applications).</li><li>‏<a rel="external nofollow" href="http://backbonejs.org/">Backbone‏</a> مكتبة JavaScript لإنشاء تطبيقات ويب بنمط MVC.</li></ul><p>نجد أن معظم إضافات وتحسينات أطر العمل والمكتبات الشهيرة تستخدم هذه الأداة، وذلك كي تضمن استخدام نسخة محددة من إطار العمل أو المكتبة التي تم إنشاء هذه الإضافة لها. لتجنب مشاكل التوافقيّة بينها.</p><h2>كيف أبدأ؟</h2><h3>مُتطلّبات الاستخدام</h3><p>يحتاج Bower إلى وجود بيئة <strong>Node.js</strong> مع مدير الحزم الخاصّ بها <strong>npm</strong> وإلى نظام <strong>git</strong> على الحاسوب المراد تثبيت الأداة عليه.</p><h4>تثبيت NodeJS</h4><p>بالنسبة لمستخدمي Windows وMac OS، يمكن التوجه <a rel="external nofollow" href="http://nodejs.org/download/">لموقع Node.js‏</a> وتنزيل ملف التثبيت المناسب حسب نظام التشغيل.</p><p>إن كنت تعمل على Linux يمكنك اتباع الطريقة السابقة. أو يمكن تثبيت Node.js عن طريق المستودعات الخاصّة بنظام التشغيل، مثلاً إن كنت تستخدم Ubuntu أو أحد مشتقاته، يمكن تثبيت Node.js عن طريق سطر الأوامر:</p><pre class="ipsCode prettyprint">sudo apt-get install nodejs npm</pre><h4>تثبيت git</h4><p>بطريقة مشابهة لتثبيت Node.js، يمكن التوجه <a rel="external nofollow" href="http://git-scm.com/download">لموقع git الرسمي</a> وتنزيل ملف التثبيت المناسب لنظام التشغيل.</p><p>إن كنت تعمل على توزيعة Linux يمكن تثبيت git باستخدام المستودعات الخاصّة بنظام التشغيل، في حال استخدام توزيعة Ubuntu أو أحد مشتقاتها، يمكن تثبيت git عن طريق الأمر:</p><pre class="ipsCode prettyprint">sudo apt-get install git</pre><h4>سطر الأوامر</h4><p>إن كنت تعمل على Windows فسطر الأوامر هو واجهة DOS أو اختصاراً هو <code>cmd</code>. وإن كنت تعمل على Linux فهناك عدد من البرامج للتعامل مع سطر الأوامر أشهرها GNOME Terminal بحسب التوزيعة والواجهة التي تستخدمها. وإن كنت تعمل على Mac OS فيمكن أن تستخدم iTerm.</p><h3>التثبيت</h3><p>بعد التأكد من وجود المُتطلّبات على حاسوبك، ما عليك سوى فتح سطر الأوامر (command line) ثمّ كتابة الأمر:</p><pre class="ipsCode prettyprint">npm install -g bower</pre><p><strong>ملاحظة:</strong> إن كنت تعمل على نظام Linux أو Mac OS وفشلت عملية التثبيت قد تحتاج لإضافة أمر <code>sudo</code> في البداية ليتم استخدام صلاحيات الجذر (root) في التثبيت، فيصبح الأمر:</p><pre class="ipsCode prettyprint">sudo npm install -g bower</pre><p>تهانينا! أصبحت أداة Bower موجودة على حاسوبك وقابلة للاستخدام. تابع معنا كيف تستخدمها.</p><h2>استخدام Bower</h2><p>أداة Bower هي أداة تعمل في سطر الأوامر، جميع الأوامر التي سنستخدمها تحتاج إلى كتابتها في سطر الأوامر (Command Line).</p><p>لنقم بفتح سطر الأوامر، ولنقم بإنشاء مجلد اسمه <code>bower_tutorials</code> ثمّ نتوجه إليه في المكان الذي قمنا بإنشاء المجلد فيه:</p><pre class="ipsCode prettyprint">cd /home/ammar/www/bower_tutorials/</pre><p>أصبحنا الآن جاهزين لبدء استخدام Bower.</p><h3>1. تثبيت الحزم</h3><p>ما رأيك لو نقوم بتثبيت jQuery الشهيرة؟ أمر سهل، لنكتب هذا الأمر في سطر الأوامر:</p><pre class="ipsCode prettyprint">bower install jquery</pre><p>أصبحت مكتبة jQuery الشهيرة موجودة في المجلد الذي أنشأته، داخل مجلد اسمه <code>bower_components</code>.</p><p>حسناً، لنقم بتثبيت إطار عمل Twitter Bootstrap لكن بنسخة قديمة هي 3.1.1، يمكن ذلك عن طريق:</p><pre class="ipsCode prettyprint">bower install bootstrap#3.1.1</pre><p>أصبح Twitter Bootstrap بنسخته القديمة 3.1.1 جاهزاً، ما رأيكم بسهولة الأمر مقارنة بالطريقة التقليدية؟ <img title=":)" alt=":)" src="https://academy.hsoub.com/uploads/monthly_2015_02/smile.png.cf72ab87c1aaefd42371e0a7de39cfae.png"></p><p>في الطريقة الأولى عندما قمنا بتثبيت jQuery لم نقم بتحديد الإصدار الذي نريده. في هذه الحالة يقوم Bower تلقائياً بتحميل آخر نسخة من المكوّن المطلوب. ويمكن أيضاً أن نفعل كما في المثال الثاني حيث قمنا بتحديد النسخة المطلوبة بذاتها.</p><h3>2. البحث عن الحزم</h3><p>قد يحدث أن تقوم بطلب تثبيت حزمة أو مكوّن ولا يتم تثبيته، يمكن أن تتأكد من وجود الحزمة عن طريق البحث. لنبحث عن Bootstrap ولنرَ ماذا يحوي مستودع Bower، نكتب:</p><pre class="ipsCode prettyprint">bower search bootstrap</pre><p>نرى عدداً كبيراً من نتائج البحث ظهرت في سطر الأوامر، كيف نعرف ما هي الحزمة التي نريدها من بين كل تلك الحزم؟ إن كنا نريد تثبيت مكوّن شهير، فغالباً ما تكون أول نتيجة بحث هي الحزمة المطلوبة، أول نتيجة تظهر في البحث السابق هي:</p><pre class="ipsCode prettyprint">    bootstrap git://github.com/twbs/bootstrap.git</pre><p>نستفيد من البحث في حال كنا نبحث عن نسخة من الحزمة المطلوبة، أو عن إضافة لها، فمثلاً نجد ضمن نتائج البحث:</p><pre class="ipsCode prettyprint">bootstrap-sass-twbs git://github.com/twbs/bootstrap-sass.git</pre><p>هذه نسخة رسمية من Twitter Bootstrap لكنها مخصّصة للعمل مع Sass بدلاً من ملفات CSS جاهزة.</p><h3>3. حذف الحزم</h3><p>بعد أن أصبح تثبيت الحزم واضحاً، ماذا لو قمتَ بتثبيت حزمة ثمّ لم تعد تريدها، أو قمتَ بتثبيت حزمة خاطِئة غير التي تريدها؟</p><p>لحذف الحزمة يمكن استخدام الأمر:</p><pre class="ipsCode prettyprint">bower uninstall bootstrap-sass-twbs</pre><p>كما يمكن حذف عدة حزم دفعة واحدة في نفس الأمر:</p><pre class="ipsCode prettyprint">bower uninstall bootstrap jquery fontawesome</pre><h3>4. عن ملف <code>bower.json</code>: أهميته واستخداماته</h3><p>لنفرض أنّك تعمل ضمن فريق، وقمتَ بتثبيت آخر نسخة من jQuery وآخر نسخة من Twitter Bootstrap، ثمّ بعد شهرين قام زميلك في العمل بتثبيت نفس الحزم. لكنّه تفاجئ أن هناك أخطاء بدأت بالظهور لم تكن تظهر من قبل. بدأ يبحث عن المشكلة وعن الحزم المنصبة، وجد أن إصدارات الحزم التي قام بتثبيتها تختلف عن إصدارات الحزم التي قمتَ بتثبيتها منذ شهرين، عندما كان المشروع يعمل بشكل جيد!</p><p>مثال آخر، لنفرض أنك تعمل في فريق، وأحد زملائك لا يعرف ما هي المُتطلّبات التي يحتاجها المشروع، هو يريد فقط أن يقوم بتجربة المشروع. سيحتاج إلى طريقة لتثبيت الحزم المطلوبة جميعها قبل أن يقوم بتشغيل المشروع ليرى كيف يبدو. لكنه غير مختص ولا يعرف كيف!</p><p>الحل للمثالين هو استخدام ملف <code>bower.json</code>.</p><p>ما هو هذا الملف؟ هو ملف يقوم بتعريف الحزم المستخدم في المشروع مع رقم الإصدار الخاصّ بكل حزمة، ثمّ يمكن تثبيت الحزم عن طريق الأمر:</p><pre class="ipsCode prettyprint">bower install</pre><p>هو نفسه أمر التثبيت لكن بدون ذكر أي حزم بعده، سيقوم عندها Bower بالبحث عن ملف <code>bower.json</code> وتثبيت الحزم المذكورة فيه حسب الإصدارات المذكورة.</p><p>بهذه الطريقة يمكن لأي شخص من فريق العمل أن يقوم بتثبيت جميع المُتطلّبات بشكل بسيط وسهل دون أن يعرفوا الحزم وإصداراتها المطلوبة.</p><h4>كيفية إنشاء ملف <code>bower.json</code> ووضع الحزم المطلوبة بداخله</h4><p>يمكن إنشاء ملف <code>bower.json</code> باستخدام أي محرر نصوص، لكن الطريقة الأفضل هي استخدام الأمر الخاصّ بإنشاءه عن طريق الأداة نفسها، كما يلي:</p><pre class="ipsCode prettyprint">bower init</pre><p>بعد ضغط زرّ <code>Enter</code> تظهر بضع أسئلة (خطوات)، يمكن أن يتم تجاهل الخطوات جميعها عدا الخطوة الأولى، فيجب ألا تكون فارغة. لكن الأفضل اتباع الخطوات والإجابة على الأسئلة جميعها حتى يصبح المشروع أوضح.</p><p>الخطوات هي:</p><pre class="ipsCode prettyprint">? name: bower-introduction</pre><p>يسأل هنا عن اسم المشروع، يجعل اسم المجلد الحالي هو اسم المشروع بشكل افتراضيّّ، إن تم ضغط زرّ <code>Enter</code> يتم استخدام اسم المجلد، أو يتم كتابة اسم المشروع ثمّ ضغط زرّ <code>Enter</code>.</p><pre class="ipsCode prettyprint">? version: 0.0.0</pre><p>يسأل هنا عن إصدار المشروع الجديد الذي تريد إنشاء ملف <code>bower.json</code> من أجله. بشكل افتراضيّ يكون الإصدار هو <code>0.0.0</code> ويمكن تغييره بكتابة رقم جديد وضغط زرّ <code>Enter</code>.</p><pre class="ipsCode prettyprint">? description:</pre><p>هنا نضع وصفاً للمشروع الحالي ثمّ نضغط زرّ <code>Enter</code>.</p><pre class="ipsCode prettyprint">? main file:</pre><p>هنا نضع الملف الرئيسي للمشروع مثلاً: <code>index.html</code>.</p><pre class="ipsCode prettyprint">? what types of modules does this package expose?:</pre><p>المقصود من هذا السؤال هو تحديد آلية عمل الوحدات المكوِّنة للمشروع (modules) عند كونه مشروع JavaScript متقدّماً.</p><p>تظهر في هذا السؤال 5 خيارات هي: <code>amd</code> و<code>es6</code> و<code>globals</code> و<code>node</code> و<code>yui</code>. بشكل افتراضيّ لا يكون أي خيار منها محدداً. يمكن تحريك المؤشر باستخدام السهمين أعلى وأسفل، ثمّ ضغط زرّ المسافة لتحديد الخيار/الخيارات المطلوبة. ثمّ نضغط زرّ <code>Enter</code> للمتابعة إلى الخطوة التالية.</p><pre class="ipsCode prettyprint">? keywords:</pre><p>الكلمات المفتاحية للمشروع مفصولة بفواصل <code>,</code>.</p><pre class="ipsCode prettyprint">? authors: Ammar Alakkad &lt;am.alakkad@gmail.com&gt;</pre><p>اسم أو أسماء المطورين للمشروع، يمكن أن يتم وضع اسم المطور يليه بريده الإلكتروني بين قوسين <code>Name &lt;email@example.com&gt;‎</code>. بشكل افتراضيّ يأخذ Bower الاسم والبريد الإلكتروني من إعدادات git الموجودة على الحاسوب.</p><pre class="ipsCode prettyprint">? license: MIT</pre><p>رخصة استخدام المشروع بشكل مختصر. إن كنت مهتمّاً بمعرفة أشهر الرخص ومتى تَستخدم كل واحدة يمكن الذهاب لموقع <a rel="external nofollow" href="http://choosealicense.com">Choose an OSS license‏</a> يحوي توضيحاً بالإنكليزية.</p><pre class="ipsCode prettyprint">? homepage:</pre><p>رابط صفحة المشروع على الإنترنت إن وجدت.</p><pre class="ipsCode prettyprint">? set currently installed components as dependencies?: Yes</pre><p>إن كانت بعض الحزم قد ثُبتّت قبل إنشاء الملف، هل تريد أن يتم وضعها ضمن الحزم المطلوبة في الملف؟</p><pre class="ipsCode prettyprint">? add commonly ignored files to ignore list?: Yes</pre><p>إضافة الملفات المتعارف على إضافتها إلى لائحة التجاهل في ملف <code>bower.json</code>، عادة ما تكون هذه الملفات ملفات غير مفيدة لمستخدم الحزمة. لكن قد يكون مطور الحزمة المُستخدَمة قد أضافها إلى ملفات حزمته، كملفات التجارب، أو مجلد <code>bower_components</code> الخاص بالحزمة المطوَّرة.</p><pre class="ipsCode prettyprint">? would you like to mark this package as private which prevents it from being accidentally published to the registry?: Yes</pre><p>هل تريد جعل الحزمة خاصّة بحيث لا يتم إضافة على مستودعات Bower؟ الإجابة الافتراضيّة هي نعم. إن أردت أن تكون الحزمة خاصّة دون نشرها يمكن كتابة كلمة <code>yes</code> ثمّ ضغط زرّ <code>Enter</code>.</p><h4>الفرق بين المُتطلّبات ومُتطلّبات التطوير</h4><p><strong>مُتطلّبات التطوير</strong> نستخدمها عند الرّغبة بالتطوير على المشروع نفسه، تحوي حزم مثل Unit Testing أو مُنشئ الوثائق (documentation).</p><p><strong>المُتطلّبات</strong> هي الحزم المطلوبة لاستخدام المشروع. مثلاً عندما نستخدم إطار عمل Zurb Foundation نحتاج معه إلى مكتبة jQuery. جميع المُتطلّبات التي نحتاجها لتشغيل المشروع وليس إلى تطويره تعتبر من المُتطلّبات.</p><h3>5. هل يمكن تثبيت الحزم في مجلد مختلف؟</h3><p>قد يرغب البعض بعدم تسمية مجلد الحزم بالاسم الافتراضيّ <code>bower_components</code> ويريد تغييره. لا يجب تغيير هذا الاسم عن طريق إعادة التسمية، بل يتم إضافة ملف آخر يوضع فيه اسم المجلد المرغوب بوضع الحزم بداخله.</p><p>نقوم بإنشاء ملف باسم <code>‎.bowerrc</code> نضع بداخله:</p><pre class="javascript ipsCode prettyprint">{
    {
        "directory": "my_components"
    }
}</pre><p>بهذا عند تثبيت أو تحديث الحزم، سيتم وضعها في مجلد <code>my_components</code> بدلاً من المجلد الافتراضيّّ.</p><h3>6. هل هناك أدوات تدعم وتتناغم مع Bower؟</h3><p>هناك عدد من الأدوات التي تدعم Bower منها:</p><ul><li>‏<a rel="external nofollow" href="https://incident57.com/codekit/">CodeKit‏</a> تطبيق لنظام تشغيل Mac OS مخصّص لإنشاء المواقع.</li><li>‏<a rel="external nofollow" href="https://github.com/benschwarz/sublime-bower">Sublime Bower‏</a> إضافة لمحرر النصوص الشهير Sublime Text تسمح بتثبيت الحزم من خلال البرنامج نفسه.</li><li>‏<a rel="external nofollow" href="https://github.com/gdi2290/atom-bower-install">Atom Bower Install‏</a> إضافة لمحرر Atom مفتوح المصدر تقوم بتثبيت الحزم من خلال البرنامج نفسه.</li><li>‏<a rel="external nofollow" href="https://www.jetbrains.com/webstorm">WebStorm‏</a> بيئة متكاملة لتطوير مواقع الويب تتميز بتكامل قويّ جداً مع JavaScript، يملك هذا البرنامج دعماً مدمجاً به لأداة Bower.</li><li>‏<a rel="external nofollow" href="https://visualstudio.com/free">Visual Studio 2015‏</a> النسخة الأخيرة من Visual Studio مدمجة مع دعم لأداة Bower للبحث وتثبيت الحزم.</li><li>‏<a rel="external nofollow" href="https://visualstudiogallery.msdn.microsoft.com/65748cdb-4087-497e-a394-2e3449c8e61e">Package Intellisense for Visual Studio 2013‏</a> إضافة مخصّصة لـ Visual Studio لإضافة دعم مدير حزم Node.js مع أداة Bower.</li></ul><p>هناك أيضاً عدد من الإضافات الخاصّة بمشغّلات المهام Grunt وGulp وbroccoli.</p><h3>أي نوع من المشاريع يمكنني استخدام Bower معه؟</h3><p>يمكنك استخدام Bower في أي مشروع ويب يحتاج إلى واجهاتٍ تظهر للمستخدم (front-end). سواء كانت المكوِّنات للاستخدام المباشر أو لمعالجتها واستخدامها في بناء مكوّنات مخصّصة بناءً على مُتطلّبات التصميم.</p><p>كما قرأنا معاً، Bower أداة بسيطة الاستخدام، تساعد بإدارة الحزم الخاصّة بمشاريع الويب، بشكل يسهّل استخدامها ويضمن الحصول على الإصدارات المطلوبة. كما يسهّل تعامل عدد من المطورين معاً في نفس المشروع، عن طريق حصولهم على نفس المُتطلّبات بالإصدارات المحددة.</p><p>أرجو أن تكونوا قد استفدتم من هذا الشرح، في حال وجود أيّ استفسار أو تساؤل لا تتردّدوا بوضعه في التعليقات.</p>
]]></description><guid isPermaLink="false">15</guid><pubDate>Tue, 03 Mar 2015 19:10:00 +0000</pubDate></item></channel></rss>
