<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><title>صِوان مِحور الابعاد الثلاث XYZ</title><description>صوان مدونة تقنية تعليمية تقدم دروس في احتراف بلوجر و اليوتيوب و الربح من الانترنت.</description><managingEditor>noreply@blogger.com (جمال الحزازي)</managingEditor><pubDate>Mon, 5 Oct 2026 10:28:21 GMT</pubDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">173</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">25</openSearch:itemsPerPage><link>https://www.siwane.xyz/</link><language>en-us</language><itunes:explicit>no</itunes:explicit><copyright>يمنع منعاً باثا اعادة نشر المحتوى بدون استشارة او تصريح من المؤلف اي فعل ناجم عن ذلك يتابع صاحبه متابعة قضائية </copyright><itunes:image href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVV8Hc7VfpuBYjPLouiZoHfFk8jELZYY-sGUuX3h2LpYzq3NyIjnjq7bw4jp7MJDbDbomklEBHCndmI-GJ5E7H47VU-yA2fS_QWKd4aqkRBmoLbPyT5pmuKZwDQzKNFavzJP5jGEYkrPsS-dCe3Ysxlgn6SadZM2dDnXez8OU-TSLpwVAu7P3BYXCu/s1600-rw/podcasts.webp"/><itunes:keywords>صِوان XYZ, احتراف التدوين, الربح من الانترنت, احتراف اليوتيوب, احتراف السيو, مراجعة السيو,podcast</itunes:keywords><itunes:summary>بودكاست صِوان XYZ يطرح مواضيع لها علاقة بمحتوى الموقع من احتراف التدوين و اليوتيوب و التقنية بشكل عام.</itunes:summary><itunes:subtitle>Podcasts SiwaneXYZ</itunes:subtitle><itunes:category text="Education"><itunes:category text="Educational Technology"/></itunes:category><itunes:author>صِوان مِحور الابعاد الثلاث XYZ</itunes:author><itunes:owner><itunes:email>jamal@elhizazi.me</itunes:email><itunes:name>صِوان مِحور الابعاد الثلاث XYZ</itunes:name></itunes:owner><item><title>حل مشكلة MongoServerError: unknown operator: $expr في MongoDB 6.10.0</title><link>https://www.siwane.xyz/2026/10/mongodb.html</link><category>مقالات AI</category><pubDate>Mon, 5 Oct 2026 10:27:50 GMT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-4850305627946300699</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="حل مشكلة MongoServerError: unknown operator: $expr في MongoDB 6.10.0" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;استكشف الأسباب والحلول العملية لخطأ "unknown operator: $expr" في MongoDB 6.10.0، مع التركيز على التحقق من الإصدار والصياغة الصحيحة.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; هذا المقال، سنتناول مشكلة تقنية محددة قد تواجهها عند العمل مع MongoDB، وهي الخطأ "MongoServerError: unknown operator: $expr" على الرغم من استخدامك للإصدار 6.10.0. يعد عامل التشغيل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; أداة قوية تسمح لك ببناء تعبيرات استعلام تستخدم تعبيرات التجميع داخل مرحلة &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$match&lt;/code&gt;&lt;/b&gt;، وقد تم تقديمه في MongoDB 3.6. لذا، فإن ظهوره كـ "عامل تشغيل غير معروف" في إصدار حديث مثل 6.10.0 أمر غير متوقع ويشير عادةً إلى مشكلة أساسية تحتاج إلى تشخيص دقيق.&lt;/p&gt;

&lt;h2 id="understanding-the-error"&gt;فهم الخطأ: "unknown operator: $expr"&lt;/h2&gt;
&lt;p&gt;يحدث الخطأ "MongoServerError: unknown operator: $expr" عندما يحاول خادم MongoDB معالجة استعلام يتضمن عامل التشغيل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt;، لكنه يفشل في التعرف عليه. في الظروف العادية، يجب أن يتعرف MongoDB 6.10.0 على هذا العامل دون أي مشاكل، حيث إنه مدعوم منذ سنوات عديدة. هذا التناقض هو ما يجعل هذا الخطأ محيرًا ويستدعي فحصًا منهجيًا.&lt;/p&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يسمح عامل التشغيل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; باستخدام تعبيرات التجميع (aggregation expressions) مباشرة داخل مرحلة &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$match&lt;/code&gt;&lt;/b&gt;، مما يتيح لك مقارنة الحقول داخل نفس المستند أو إجراء عمليات حسابية معقدة كجزء من معايير التصفية.&lt;/p&gt;

&lt;h2 id="potential-causes"&gt;الأسباب المحتملة للخطأ&lt;/h2&gt;
&lt;p&gt;على الرغم من أن MongoDB 6.10.0 يدعم &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt;، إلا أن هناك عدة أسباب محتملة لظهور هذا الخطأ:&lt;/p&gt;

&lt;h3 id="incorrect-mongodb-version"&gt;إصدار MongoDB غير صحيح أو قديم&lt;/h3&gt;
&lt;p&gt;هذا هو السبب الأكثر شيوعًا. قد تعتقد أنك متصل بإصدار 6.10.0، ولكنك في الواقع متصل بمثيل MongoDB أقدم لا يدعم &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; (أي إصدار أقدم من 3.6). يمكن أن يحدث هذا بسبب:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;تشغيل مثيل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;mongod&lt;/code&gt;&lt;/b&gt; قديم على نفس الجهاز.&lt;/li&gt;
    &lt;li&gt;الاتصال بخادم MongoDB مختلف عن المقصود.&lt;/li&gt;
    &lt;li&gt;مشاكل في بيئة الحاويات (Docker) حيث يتم تشغيل إصدار قديم عن طريق الخطأ.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="syntax-or-usage-errors"&gt;أخطاء في الصياغة أو الاستخدام&lt;/h3&gt;
&lt;p&gt;على الرغم من أن الخطأ يشير إلى "عامل تشغيل غير معروف"، إلا أن أخطاء الصياغة الدقيقة يمكن أن تؤدي أحيانًا إلى رسائل خطأ مضللة. تأكد من أن &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; مستخدم بشكل صحيح ضمن سياق استعلام التجميع (aggregation pipeline).&lt;/p&gt;

&lt;h3 id="outdated-drivers-or-clients"&gt;برامج التشغيل أو العملاء القديمة&lt;/h3&gt;
&lt;p&gt;في حالات نادرة جدًا، قد لا يقوم برنامج تشغيل MongoDB (مثل برنامج تشغيل Node.js أو Python) أو أداة العميل (مثل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;mongosh&lt;/code&gt;&lt;/b&gt;) بإرسال الاستعلام بشكل صحيح إلى الخادم إذا كان قديمًا جدًا ولا يدعم ميزات الإصدارات الأحدث. ومع ذلك، فإن هذا أقل احتمالًا بكثير من مشكلة إصدار الخادم.&lt;/p&gt;

&lt;h3 id="cluster-inconsistency"&gt;عدم اتساق في مجموعة النسخ المتماثلة/المجزأة&lt;/h3&gt;
&lt;p&gt;إذا كنت تعمل في بيئة مجموعة نسخ متماثلة (replica set) أو مجموعة مجزأة (sharded cluster)، فقد تكون بعض العقد (nodes) تعمل بإصدار أقدم من MongoDB، بينما تعتقد أن المجموعة بأكملها تعمل بالإصدار 6.10.0. يمكن أن يؤدي الاستعلام الذي يصل إلى عقدة قديمة إلى هذا الخطأ.&lt;/p&gt;

&lt;h2 id="practical-solutions"&gt;حلول عملية ومباشرة&lt;/h2&gt;

&lt;h3 id="verify-mongodb-version"&gt;التحقق من إصدار MongoDB الفعلي&lt;/h3&gt;
&lt;p&gt;هذه هي الخطوة الأكثر أهمية. يجب عليك التحقق من الإصدار الفعلي لمثيل MongoDB الذي تتصل به.&lt;/p&gt;
&lt;ol class='steps'&gt;
    &lt;li&gt;اتصل بمثيل MongoDB باستخدام &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;mongosh&lt;/code&gt;&lt;/b&gt; أو برنامج تشغيل العميل الخاص بك.&lt;/li&gt;
    &lt;li&gt;نفّذ الأمر التالي للتحقق من إصدار الخادم:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='MongoDB Shell' data-source='mongosh'&gt;&lt;code&gt;db.version()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;يجب أن تكون النتيجة مشابهة لما يلي:&lt;/p&gt;
&lt;pre data-comment='مثال على الإخراج' data-source='console'&gt;&lt;code&gt;"6.0.10" &lt;mark class='red block' data-after='(مثال لخطأ محتمل)'&gt;// إذا رأيت إصدارًا أقل من 3.6، فهذا هو السبب.&lt;/mark&gt;
&lt;mark class='green block' data-after='(الإصدار الصحيح)'&gt;// إذا رأيت "6.0.10" أو أعلى، فالمشكلة ليست في إصدار الخادم.&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;بالإضافة إلى ذلك، يمكنك التحقق من &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;featureCompatibilityVersion&lt;/code&gt;&lt;/b&gt;، والذي يحدد مجموعة الميزات المتوافقة مع الإصدار:&lt;/p&gt;
&lt;pre data-comment='MongoDB Shell' data-source='mongosh'&gt;&lt;code&gt;db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;يجب أن يكون الإخراج مشابهًا لـ &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;{ "featureCompatibilityVersion" : { "version" : "6.0" }, "ok" : 1 }&lt;/code&gt;&lt;/b&gt; أو أعلى. إذا كان الإصدار أقل من 3.6، فهذا يؤكد أنك متصل بمثيل قديم.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
    &lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;
    إذا وجدت أنك متصل بإصدار قديم، فتأكد من إيقاف تشغيل جميع مثيلات &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;mongod&lt;/code&gt;&lt;/b&gt; القديمة وبدء تشغيل المثيل الصحيح (6.10.0) أو الاتصال بالخادم الصحيح.
&lt;/div&gt;

&lt;h3 id="review-query-syntax"&gt;مراجعة صياغة الاستعلام&lt;/h3&gt;
&lt;p&gt;تأكد من أن استخدامك لـ &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; صحيح ضمن مرحلة &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$match&lt;/code&gt;&lt;/b&gt; في استعلام التجميع. إليك مثال على الاستخدام الصحيح:&lt;/p&gt;
&lt;pre data-comment='MongoDB Query' data-source='query.js'&gt;&lt;code&gt;db.collection.aggregate([
  {
    $match: {
      &lt;mark class='green'&gt;$expr&lt;/mark&gt;: {
        $gt: [ "$fieldA", "$fieldB" ] // مقارنة قيم حقلين داخل نفس المستند
      }
    }
  }
])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;في هذا المثال، يقوم &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; بتضمين تعبير تجميع &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$gt&lt;/code&gt;&lt;/b&gt; (أكبر من) لمقارنة قيم &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;fieldA&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;fieldB&lt;/code&gt;&lt;/b&gt;.&lt;/p&gt;

&lt;h3 id="update-mongodb-driver"&gt;تحديث برنامج تشغيل MongoDB&lt;/h3&gt;
&lt;p&gt;إذا كنت قد تأكدت من أن خادم MongoDB يعمل بالإصدار 6.10.0، ولكن المشكلة لا تزال قائمة، ففكر في تحديث برنامج تشغيل MongoDB الخاص بلغتك البرمجية إلى أحدث إصدار مستقر. على سبيل المثال:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;Node.js:&lt;/b&gt; &lt;code&gt;npm update mongodb&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;Python:&lt;/b&gt; &lt;code&gt;pip install --upgrade pymongo&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;Java:&lt;/b&gt; تحديث التبعية في ملف &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;pom.xml&lt;/code&gt;&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;build.gradle&lt;/code&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="ensure-cluster-uniformity"&gt;ضمان توحيد إصدارات العقد&lt;/h3&gt;
&lt;p&gt;إذا كنت تعمل مع مجموعة نسخ متماثلة أو مجموعة مجزأة، تأكد من أن جميع أعضاء المجموعة يعملون بالإصدار 6.10.0. يمكنك التحقق من إصدار كل عضو عن طريق الاتصال به بشكل فردي وتشغيل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;db.version()&lt;/code&gt;&lt;/b&gt;. إذا كانت هناك أي عقدة قديمة، فستحتاج إلى ترقيتها.&lt;/p&gt;

&lt;div class='alert error outline'&gt;
    &lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;
    يجب أن يتم ترقية مجموعات النسخ المتماثلة والمجموعات المجزأة بعناية فائقة ووفقًا لإرشادات ترقية MongoDB الرسمية لتجنب فقدان البيانات أو تعطل الخدمة.
&lt;/div&gt;

&lt;h2 id="faq"&gt;الأسئلة الشائعة&lt;/h2&gt;
&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هو عامل التشغيل $expr وما فائدته؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;عامل التشغيل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; في MongoDB يسمح لك باستخدام تعبيرات التجميع (aggregation expressions) داخل مرحلة &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$match&lt;/code&gt;&lt;/b&gt;. فائدته الرئيسية هي تمكين الاستعلامات المعقدة التي تتطلب مقارنة حقول داخل نفس المستند، أو إجراء عمليات حسابية، أو استخدام منطق شرطي كجزء من معايير التصفية، مما يوفر مرونة كبيرة في الاستعلامات.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;لماذا قد يظهر خطأ "unknown operator: $expr" في إصدار حديث مثل 6.10.0؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;على الرغم من أن &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;$expr&lt;/code&gt;&lt;/b&gt; مدعوم منذ MongoDB 3.6، فإن ظهوره كـ "عامل تشغيل غير معروف" في الإصدار 6.10.0 يشير غالبًا إلى أنك متصل عن طريق الخطأ بمثيل MongoDB أقدم من 3.6. الأسباب الشائعة تشمل تشغيل مثيلات متعددة من MongoDB، أو الاتصال بالخادم الخطأ، أو عدم اتساق الإصدارات في مجموعة النسخ المتماثلة/المجزأة. من الضروري التحقق من الإصدار الفعلي للخادم الذي تتصل به.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;p&gt;في الختام، على الرغم من أن الخطأ "MongoServerError: unknown operator: $expr" قد يبدو محيرًا في MongoDB 6.10.0، إلا أن الحل يكمن دائمًا تقريبًا في التحقق من الإصدار الفعلي لمثيل MongoDB الذي تتصل به. بمجرد التأكد من أنك تعمل على الإصدار الصحيح وأن صياغة الاستعلام دقيقة، يجب أن يتم حل المشكلة.&lt;/p&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/10/mongodb.html'&gt;حل مشكلة MongoServerError: unknown operator: $expr في MongoDB 6.10.0&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>إتقان سطر الأوامر: دليلك الشامل لأوامر Git Bash</title><link>https://www.siwane.xyz/2026/09/git-bash.html</link><category>مقالات AI</category><pubDate>Mon, 28 Sep 2026 10:27:49 GMT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-1282927438803656352</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="إتقان سطر الأوامر: دليلك الشامل لأوامر Git Bash" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;دليل عملي ومباشر لأوامر Git Bash الأساسية والمتقدمة، يشمل التهيئة، إدارة المستودعات، الفروع، والتعامل مع الأخطاء.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;يُعد Git Bash أداة قوية وضرورية للمطورين، حيث يوفر بيئة سطر أوامر شبيهة بـ Unix على أنظمة التشغيل Windows، مما يتيح التفاعل الفعال مع نظام التحكم بالإصدار Git. يركز هذا المقال على تقديم حلول عملية لأوامر Git Bash الأكثر استخدامًا، مع التركيز على الدقة والوضوح.&lt;/p&gt;

&lt;h2 id="ما-هو-git-bash"&gt;ما هو Git Bash؟&lt;/h2&gt;
&lt;p&gt;Git Bash هو تطبيق يوفر طبقة محاكاة لـ Bash (Bourne Again SHell) لتشغيل أوامر Git على نظام Windows. يشتمل على Git نفسه، بالإضافة إلى أدوات مساعدة أخرى مثل SSH و SCP، مما يجعله بيئة متكاملة لإدارة مشاريعك البرمجية والتعامل مع المستودعات المحلية والبعيدة.&lt;/p&gt;

&lt;h2 id="تهيئة-git-والإعدادات-الأولية"&gt;تهيئة Git والإعدادات الأولية&lt;/h2&gt;
&lt;p&gt;قبل البدء في استخدام Git، من الضروري تهيئة اسم المستخدم والبريد الإلكتروني الخاص بك. هذه المعلومات ستظهر في جميع التزاماتك (commits).&lt;/p&gt;
&lt;ol class='steps'&gt;
  &lt;li&gt;&lt;b&gt;تعيين اسم المستخدم:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git config --global user.name "اسمك هنا"&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تعيين البريد الإلكتروني:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git config --global user.email "بريدك_الإلكتروني@مثال.كوم"&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التحقق من الإعدادات:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git config --list&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="أوامر-git-الأساسية"&gt;أوامر Git الأساسية&lt;/h2&gt;

&lt;h3 id="إنشاء-مستودع-جديد"&gt;إنشاء مستودع جديد&lt;/h3&gt;
&lt;p&gt;لتحويل مجلد مشروعك إلى مستودع Git، استخدم الأمر &lt;code&gt;git init&lt;/code&gt;. هذا ينشئ مجلد &lt;code&gt;.git&lt;/code&gt; مخفيًا يحتوي على جميع البيانات اللازمة لتتبع التغييرات.&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git init&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="إضافة-الملفات-والالتزام-بالتغييرات"&gt;إضافة الملفات والالتزام بالتغييرات&lt;/h3&gt;
&lt;p&gt;بعد إجراء التغييرات على ملفاتك، تحتاج إلى "إضافة" هذه التغييرات إلى منطقة التجهيز (staging area) ثم "الالتزام" بها (commit) لتسجيلها في سجل Git.&lt;/p&gt;
&lt;ol class='steps'&gt;
  &lt;li&gt;&lt;b&gt;إضافة ملف واحد:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git add اسم_الملف.txt&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إضافة جميع الملفات المعدلة:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git add .&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الالتزام بالتغييرات:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git commit -m "رسالة وصفية للالتزام"&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يجب أن تكون رسالة الالتزام واضحة وموجزة لتصف التغييرات التي تم إجراؤها.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="التحقق-من-الحالة-والسجل"&gt;التحقق من الحالة والسجل&lt;/h3&gt;
&lt;p&gt;لمعرفة حالة مستودعك وسجل التغييرات، استخدم الأوامر التالية:&lt;/p&gt;
&lt;ol class='steps'&gt;
  &lt;li&gt;&lt;b&gt;عرض حالة المستودع:&lt;/b&gt; يظهر الملفات المعدلة، المضافة للتجهيز، وغير المتتبعة.
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git status&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;عرض سجل الالتزامات:&lt;/b&gt; يعرض قائمة بالالتزامات السابقة، مع معرف الالتزام، المؤلف، التاريخ، والرسالة.
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git log&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;لعرض سجل مختصر، استخدم &lt;code&gt;git log --oneline&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="التعامل-مع-المستودعات-البعيدة"&gt;التعامل مع المستودعات البعيدة&lt;/h2&gt;
&lt;p&gt;تتيح لك هذه الأوامر التفاعل مع المستودعات المستضافة على منصات مثل GitHub أو GitLab.&lt;/p&gt;

&lt;h3 id="استنساخ-مستودع-بعيد"&gt;استنساخ مستودع بعيد&lt;/h3&gt;
&lt;p&gt;لنسخ مستودع موجود من خادم بعيد إلى جهازك المحلي:&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git clone &amp;lt;URL_المستودع&amp;gt;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;مثال:&lt;/b&gt;&lt;br/&gt;&lt;code&gt;git clone https://github.com/user/repo.git&lt;/code&gt;&lt;/p&gt;

&lt;h3 id="إضافة-مستودع-بعيد"&gt;إضافة مستودع بعيد&lt;/h3&gt;
&lt;p&gt;إذا كان لديك مستودع محلي وترغب في ربطه بمستودع بعيد:&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git remote add origin &amp;lt;URL_المستودع&amp;gt;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;"origin" هو الاسم التقليدي للمستودع البعيد الرئيسي.&lt;/p&gt;

&lt;h3 id="دفع-وسحب-التغييرات"&gt;دفع وسحب التغييرات&lt;/h3&gt;
&lt;p&gt;لتبادل التغييرات بين مستودعك المحلي والمستودع البعيد:&lt;/p&gt;
&lt;ol class='steps'&gt;
  &lt;li&gt;&lt;b&gt;دفع التغييرات (Push):&lt;/b&gt; لإرسال التزاماتك المحلية إلى المستودع البعيد.
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git push -u origin main&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;الخيار &lt;code&gt;-u&lt;/code&gt; (أو &lt;code&gt;--set-upstream&lt;/code&gt;) يربط الفرع المحلي بالفرع البعيد، مما يسمح لك باستخدام &lt;code&gt;git push&lt;/code&gt; و &lt;code&gt;git pull&lt;/code&gt; لاحقًا بدون تحديد &lt;code&gt;origin main&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;سحب التغييرات (Pull):&lt;/b&gt; لجلب التغييرات من المستودع البعيد ودمجها في فرعك المحلي.
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git pull origin main&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="الفروع-والدمج"&gt;الفروع والدمج (Branching &amp; Merging)&lt;/h2&gt;
&lt;p&gt;تعتبر الفروع ميزة أساسية في Git تسمح للمطورين بالعمل على ميزات جديدة أو إصلاح الأخطاء بشكل مستقل عن الفرع الرئيسي للمشروع.&lt;/p&gt;

&lt;h3 id="إنشاء-وتبديل-الفروع"&gt;إنشاء وتبديل الفروع&lt;/h3&gt;
&lt;ol class='steps'&gt;
  &lt;li&gt;&lt;b&gt;إنشاء فرع جديد:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git branch اسم_الفرع_الجديد&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التبديل إلى فرع:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git checkout اسم_الفرع&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إنشاء وتبديل في خطوة واحدة:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git checkout -b اسم_الفرع_الجديد&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;عرض الفروع:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git branch&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;الفرع الحالي يظهر بعلامة نجمة.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="دمج-الفروع"&gt;دمج الفروع&lt;/h3&gt;
&lt;p&gt;بعد الانتهاء من العمل على فرع، يمكنك دمجه مرة أخرى في الفرع الرئيسي (أو أي فرع آخر).&lt;/p&gt;
&lt;ol class='steps'&gt;
  &lt;li&gt;&lt;b&gt;التبديل إلى الفرع الهدف:&lt;/b&gt; (مثلاً، الفرع الرئيسي &lt;code&gt;main&lt;/code&gt;)
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git checkout main&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;دمج الفرع الآخر:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git merge اسم_الفرع_للمزج&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;قد تحدث تعارضات دمج (merge conflicts) إذا كانت هناك تغييرات متضاربة في نفس الأسطر من الملفات. يجب حل هذه التعارضات يدويًا قبل إتمام الدمج.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;حذف الفرع بعد الدمج:&lt;/b&gt; (اختياري)
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git branch -d اسم_الفرع_للحذف&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="أوامر-إضافية-مفيدة"&gt;أوامر إضافية مفيدة&lt;/h2&gt;
&lt;p&gt;هذه بعض الأوامر التي قد تحتاجها في سيناريوهات مختلفة:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;التراجع عن التغييرات المحلية (قبل الالتزام):&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git restore اسم_الملف&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;للتراجع عن جميع التغييرات في المجلد الحالي (غير الملتزم بها): &lt;code&gt;git restore .&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إلغاء التجهيز (Unstaging) لملف:&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git restore --staged اسم_الملف&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التراجع عن آخر التزام (Soft Reset):&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git reset --soft HEAD~1&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;هذا يعيد الفرع إلى الالتزام السابق، مع الاحتفاظ بالتغييرات في منطقة التجهيز.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التراجع عن آخر التزام (Hard Reset):&lt;/b&gt;
    &lt;pre data-comment='Bash' data-source='command_line'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git reset --hard HEAD~1&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;هذا الأمر خطير لأنه يحذف جميع التغييرات غير الملتزم بها ويعيد المستودع إلى حالة الالتزام المحدد. استخدمه بحذر شديد.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين Git Bash و Git GUI؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;Git Bash هو واجهة سطر أوامر (CLI) تتيح لك تنفيذ أوامر Git مباشرة. بينما Git GUI هو واجهة رسومية للمستخدم (GUI) توفر طريقة مرئية للتفاعل مع Git، مما قد يكون أسهل للمبتدئين ولكنه أقل مرونة وقوة من سطر الأوامر.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;كيف أحل تعارضات الدمج (Merge Conflicts)؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;عند حدوث تعارض، سيقوم Git بوضع علامات خاصة في الملفات المتعارضة (&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;، =======، &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;). يجب عليك فتح هذه الملفات يدويًا، وحذف العلامات، واختيار الإصدار الصحيح من الكود، ثم حفظ الملفات، وإضافتها مرة أخرى إلى منطقة التجهيز (&lt;code&gt;git add .&lt;/code&gt;)، وأخيرًا الالتزام بالدمج (&lt;code&gt;git commit&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكنني استخدام Git Bash مع أي مستودع Git بعيد؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكن لـ Git Bash التفاعل مع أي مستودع Git بعيد، سواء كان مستضافًا على GitHub، GitLab، Bitbucket، أو حتى خادم Git خاص بك، طالما أن لديك الأذونات اللازمة (عادةً عبر SSH أو HTTPS).&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;p&gt;يُعد إتقان أوامر Git Bash أمرًا بالغ الأهمية لأي مطور يسعى لتحسين سير عمله والتحكم الكامل في مشاريع البرمجيات. من خلال هذه الأوامر الأساسية والمتقدمة، يمكنك إدارة مستودعاتك بفعالية، التعاون مع الفرق، والحفاظ على سجل نظيف لتغييراتك.&lt;/p&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/09/git-bash.html'&gt;إتقان سطر الأوامر: دليلك الشامل لأوامر Git Bash&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>احتراف SVG: دليل شامل لأحدث التطورات والتقنيات</title><link>https://www.siwane.xyz/2026/09/master.html</link><category>مقالات AI</category><pubDate>Mon, 21 Sep 2026 10:28:07 GMT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-2684049596793458782</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="احتراف SVG: دليل شامل لأحدث التطورات والتقنيات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف كيفية احتراف رسومات SVG المتجهة، من الأساسيات إلى التقنيات المتقدمة، واستكشف أحدث التطورات في الرسوم المتحركة وإمكانية الوصول والأداء.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم الويب الحديث، أصبحت الرسومات المتجهة القابلة للتطوير (SVG) أداة لا غنى عنها للمطورين والمصممين. إنها توفر مرونة لا مثيل لها وجودة بصرية فائقة عبر مختلف الأجهزة والشاشات. هذا المقال يقدم دليلاً شاملاً لاحتراف SVG، بدءاً من المفاهيم الأساسية وصولاً إلى أحدث التطورات والتقنيات المتقدمة، مع التركيز على الحلول العملية.&lt;/p&gt;

&lt;h2 id="what-is-svg"&gt;ما هو SVG ولماذا هو مهم؟&lt;/h2&gt;
&lt;p&gt;SVG (Scalable Vector Graphics) هو تنسيق صور قائم على XML لرسومات ثنائية الأبعاد يدعم التفاعل والرسوم المتحركة. على عكس الصور النقطية (مثل JPEG و PNG)، لا تعتمد رسومات SVG على البكسلات، مما يعني أنها يمكن أن تتوسع إلى أي حجم دون فقدان الجودة. هذه الميزة تجعلها مثالية لتصميم الويب المتجاوب (Responsive Web Design) وتطبيقات الأجهزة المحمولة.&lt;/p&gt;
&lt;p class='pIndent'&gt;تشمل المزايا الرئيسية لـ SVG ما يلي:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;المرونة في التوسع:&lt;/b&gt; يمكن تغيير حجمها دون تشويه.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;حجم ملف صغير:&lt;/b&gt; غالباً ما تكون ملفات SVG أصغر من نظيراتها النقطية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;قابلة للتحرير:&lt;/b&gt; يمكن تحريرها باستخدام أي محرر نصوص أو برامج رسوميات متجهة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;قابلة للبحث والفهرسة:&lt;/b&gt; محتواها نصي، مما يجعلها قابلة للبحث بواسطة محركات البحث.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;قابلة للتحريك والتفاعل:&lt;/b&gt; يمكن تحريكها وتعديلها باستخدام CSS و JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="mastering-svg-core"&gt;احتراف SVG: المفاهيم الأساسية&lt;/h2&gt;
&lt;p&gt;لتبدأ في احتراف SVG، يجب فهم العناصر الأساسية التي تشكل أي رسم SVG.&lt;/p&gt;

&lt;h3 id="basic-shapes"&gt;الأشكال الأساسية والمسارات&lt;/h3&gt;
&lt;p&gt;تتكون رسومات SVG من مجموعة من الأشكال الهندسية البسيطة والمسارات المعقدة:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt;: لإنشاء مستطيلات ومربعات.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt;: لإنشاء دوائر.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;ellipse&amp;gt;&lt;/code&gt;: لإنشاء أشكال بيضاوية.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;line&amp;gt;&lt;/code&gt;: لإنشاء خطوط مستقيمة.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;polyline&amp;gt;&lt;/code&gt;: لإنشاء سلسلة من الخطوط المتصلة.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;polygon&amp;gt;&lt;/code&gt;: لإنشاء أشكال مغلقة متعددة الأضلاع.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt;: العنصر الأكثر قوة، يسمح بإنشاء أي شكل معقد باستخدام أوامر مثل &lt;b style='color:var(--linkC)'&gt;M (move to)&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;L (line to)&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;C (cubic Bezier curve)&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Z (close path)&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre data-comment='SVG Path' data-source='example.svg'&gt;&lt;code&gt;&amp;lt;svg width="200" height="200"&amp;gt;
  &amp;lt;path d="M10 10 L100 10 L100 100 L10 100 Z" fill="blue" stroke="black" stroke-width="3"/&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="transforms-and-groups"&gt;التحويلات والتجميعات&lt;/h3&gt;
&lt;p&gt;يمكن تطبيق التحويلات (مثل الترجمة، الدوران، التحجيم، الانحراف) على عناصر SVG باستخدام السمة &lt;code&gt;transform&lt;/code&gt;. لتطبيق تحويلات متعددة أو تجميع عناصر معاً، يُستخدم العنصر &lt;code&gt;&amp;lt;g&amp;gt;&lt;/code&gt; (group).&lt;/p&gt;
&lt;pre data-comment='SVG Group &amp; Transform' data-source='example.svg'&gt;&lt;code&gt;&amp;lt;svg width="200" height="200"&amp;gt;
  &amp;lt;g transform="translate(50,50) rotate(45)"&amp;gt;
    &amp;lt;rect x="0" y="0" width="50" height="50" fill="red"/&amp;gt;
  &amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="gradients-and-patterns"&gt;التدرجات والأنماط&lt;/h3&gt;
&lt;p&gt;يمكن استخدام التدرجات اللونية (&lt;code&gt;&amp;lt;linearGradient&amp;gt;&lt;/code&gt; و &lt;code&gt;&amp;lt;radialGradient&amp;gt;&lt;/code&gt;) والأنماط (&lt;code&gt;&amp;lt;pattern&amp;gt;&lt;/code&gt;) لملء الأشكال بخلفيات أكثر تعقيداً وجاذبية.&lt;/p&gt;

&lt;h3 id="text-and-fonts"&gt;النصوص والخطوط&lt;/h3&gt;
&lt;p&gt;يسمح عنصر &lt;code&gt;&amp;lt;text&amp;gt;&lt;/code&gt; بإضافة نصوص إلى رسومات SVG، ويمكن التحكم في خصائص الخط (مثل الحجم واللون والنمط) باستخدام CSS. يمكن استخدام &lt;code&gt;&amp;lt;tspan&amp;gt;&lt;/code&gt; لتنسيق أجزاء معينة من النص.&lt;/p&gt;

&lt;h2 id="advanced-svg-techniques"&gt;تقنيات SVG المتقدمة&lt;/h2&gt;
&lt;p&gt;بعد إتقان الأساسيات، يمكن للمطورين استكشاف تقنيات أكثر تقدماً لإنشاء رسومات SVG ديناميكية وتفاعلية.&lt;/p&gt;

&lt;h3 id="svg-with-css"&gt;تنسيق SVG باستخدام CSS&lt;/h3&gt;
&lt;p&gt;يمكن تنسيق عناصر SVG بالكامل باستخدام CSS، تماماً مثل عناصر HTML. يمكن التحكم في خصائص مثل &lt;code&gt;fill&lt;/code&gt; (لون التعبئة)، &lt;code&gt;stroke&lt;/code&gt; (لون الحدود)، &lt;code&gt;stroke-width&lt;/code&gt; (عرض الحدود)، وحتى &lt;code&gt;transform&lt;/code&gt; و &lt;code&gt;opacity&lt;/code&gt;.&lt;/p&gt;
&lt;pre data-comment='CSS for SVG' data-source='style.css'&gt;&lt;code&gt;rect {
  fill: #3498db;
  stroke: #2980b9;
  stroke-width: 2px;
  transition: fill 0.3s ease;
}
rect:hover {
  fill: #e74c3c;
}&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="svg-with-javascript"&gt;معالجة SVG باستخدام JavaScript&lt;/h3&gt;
&lt;p&gt;يمكن لـ JavaScript التفاعل مع رسومات SVG عن طريق معالجة نموذج كائن المستند (DOM) الخاص بها. يتيح ذلك إنشاء رسوم متحركة ديناميكية، وتغيير الخصائص بناءً على تفاعلات المستخدم، وحتى إنشاء رسومات SVG بالكامل برمجياً. مكتبات مثل &lt;a class='extL' href='https://greensock.com/gsap/' rel='nofollow noreferrer' target='_blank'&gt;GSAP&lt;/a&gt; و &lt;a class='extL' href='https://d3js.org/' rel='nofollow noreferrer' target='_blank'&gt;D3.js&lt;/a&gt; تسهل هذه العملية بشكل كبير.&lt;/p&gt;

&lt;h3 id="filters-and-clipping"&gt;الفلاتر وأقنعة القص (Clipping Paths)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;الفلاتر (&lt;code&gt;&amp;lt;filter&amp;gt;&lt;/code&gt;):&lt;/b&gt; تسمح بتطبيق تأثيرات بصرية معقدة مثل الظلال، الضبابية، وتغيير الألوان. يتم تعريف الفلاتر داخل عنصر &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; ثم يتم تطبيقها باستخدام السمة &lt;code&gt;filter&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;أقنعة القص (&lt;code&gt;&amp;lt;clipPath&amp;gt;&lt;/code&gt;):&lt;/b&gt; تُستخدم لقص جزء من الرسم، مما يظهر فقط الأجزاء التي تقع داخل شكل محدد.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="latest-svg-developments"&gt;أحدث التطورات في SVG&lt;/h2&gt;
&lt;p&gt;تستمر تقنيات الويب في التطور، و SVG ليست استثناءً. إليك بعض أحدث التطورات التي يجب على المحترفين معرفتها:&lt;/p&gt;

&lt;h3 id="svg-animations-web-animations-api"&gt;رسوم SVG المتحركة و Web Animations API (WAAPI)&lt;/h3&gt;
&lt;p&gt;بينما يمكن استخدام CSS و JavaScript لإنشاء رسوم متحركة لـ SVG، فإن &lt;b style='color:var(--linkC)'&gt;Web Animations API (WAAPI)&lt;/b&gt; يوفر طريقة أكثر قوة ومرونة لإنشاء الرسوم المتحركة المعقدة والمزامنة مباشرة في المتصفح. إنه يجمع بين قوة الرسوم المتحركة المستندة إلى CSS والتحكم الدقيق في JavaScript.&lt;/p&gt;

&lt;h3 id="svg-accessibility"&gt;إمكانية الوصول (Accessibility) في SVG&lt;/h3&gt;
&lt;p&gt;أصبحت إمكانية الوصول جزءاً لا يتجزأ من تطوير الويب. لضمان أن تكون رسومات SVG سهلة الاستخدام للجميع، بما في ذلك مستخدمي برامج قراءة الشاشة، يجب استخدام العناصر والسمات التالية:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;: يوفر عنواناً وصفياً للرسم.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;lt;desc&amp;gt;&lt;/code&gt;: يوفر وصفاً أطول وأكثر تفصيلاً.&lt;/li&gt;
  &lt;li&gt;سمات ARIA: مثل &lt;code&gt;aria-labelledby&lt;/code&gt; و &lt;code&gt;role="img"&lt;/code&gt; لربط SVG بالنص البديل.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="svg-in-web-components"&gt;SVG في مكونات الويب (Web Components)&lt;/h3&gt;
&lt;p&gt;تتيح مكونات الويب (Custom Elements, Shadow DOM) تغليف رسومات SVG المعقدة ومنطقها التفاعلي في مكونات قابلة لإعادة الاستخدام. هذا يعزز قابلية الصيانة ويقلل من تكرار الكود، مما يجعل إدارة المشاريع الكبيرة أسهل.&lt;/p&gt;

&lt;h3 id="svg-and-wasm"&gt;SVG و WebAssembly (WASM)&lt;/h3&gt;
&lt;p&gt;على الرغم من أن SVG يتم تحليله وعرضه بواسطة المتصفح، إلا أن هناك اهتماماً متزايداً باستخدام WebAssembly (WASM) لتقديم رسومات SVG المعقدة أو عمليات المعالجة الثقيلة. يمكن أن يؤدي ذلك إلى تحسينات كبيرة في الأداء لتطبيقات الويب التي تعتمد بشكل كبير على رسومات SVG الديناميكية والمعقدة.&lt;/p&gt;

&lt;h2 id="practical-tips"&gt;نصائح عملية لاحتراف SVG&lt;/h2&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;ابدأ بالأساسيات:&lt;/b&gt; تأكد من فهمك العميق للأشكال الأساسية والمسارات وكيفية عملها.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استخدم محررات الرسوم المتجهة:&lt;/b&gt; برامج مثل Inkscape (مجاني) أو Adobe Illustrator يمكن أن تساعدك في إنشاء رسومات SVG معقدة وتصديرها.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تحسين ملفات SVG:&lt;/b&gt; استخدم أدوات مثل &lt;a class='extL' href='https://github.com/svg/svgo' rel='nofollow noreferrer' target='_blank'&gt;SVGO&lt;/a&gt; لتقليل حجم ملفات SVG عن طريق إزالة البيانات غير الضرورية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تعلم CSS لتنسيق SVG:&lt;/b&gt; إتقان تنسيق SVG باستخدام CSS يفتح لك عالماً من الإمكانيات الجمالية والتفاعلية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استكشف JavaScript للتفاعل:&lt;/b&gt; تعلم كيفية معالجة SVG DOM باستخدام JavaScript لإنشاء رسوم متحركة وتفاعلات مخصصة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;ركز على إمكانية الوصول:&lt;/b&gt; اجعل رسومات SVG الخاصة بك متاحة للجميع من خلال استخدام السمات المناسبة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;ابقَ على اطلاع:&lt;/b&gt; تابع أحدث مواصفات SVG وتطورات الويب لتبقى في طليعة التقنيات.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class='alert info outline'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يمكن تضمين SVG مباشرة في HTML باستخدام وسم &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt;، أو كملف خارجي باستخدام وسم &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;، أو كصورة خلفية في CSS. كل طريقة لها مزاياها وعيوبها.&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق الرئيسي بين SVG والصور النقطية؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;الفرق الرئيسي هو أن SVG رسومات متجهة تعتمد على المعادلات الرياضية، مما يسمح بتغيير حجمها دون فقدان الجودة. بينما الصور النقطية (مثل PNG و JPEG) تعتمد على البكسلات، وتفقد جودتها عند التكبير.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكن تحريك SVG باستخدام CSS فقط؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكن تحريك SVG باستخدام خصائص CSS مثل &lt;code&gt;transform&lt;/code&gt; و &lt;code&gt;transition&lt;/code&gt; و &lt;code&gt;animation&lt;/code&gt;. ومع ذلك، قد تكون الرسوم المتحركة الأكثر تعقيداً أو التفاعلية أسهل في التنفيذ باستخدام JavaScript أو Web Animations API.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/09/master.html'&gt;احتراف SVG: دليل شامل لأحدث التطورات والتقنيات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>ربط Scroll-Timeline المشروط ضمن استعلامات حاويات CSS</title><link>https://www.siwane.xyz/2026/09/css-conditional.html</link><category>مقالات AI</category><pubDate>Mon, 14 Sep 2026 10:27:43 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-2837179730256276692</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="ربط Scroll-Timeline المشروط ضمن استعلامات حاويات CSS" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف كيف يمكنك دمج Scroll-Timeline مع استعلامات حاويات CSS لإنشاء تجارب تفاعلية متجاوبة، مع حلول عملية وفعالة.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الويب الحديث، أصبحت القدرة على إنشاء تجارب مستخدم ديناميكية ومتجاوبة أمراً حاسماً. مع ظهور &lt;b style='color:var(--linkC)'&gt;استعلامات حاويات CSS (CSS Container Queries)&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;Scroll-Timeline&lt;/b&gt;، أصبح لدى المطورين أدوات قوية لتحقيق ذلك. ومع ذلك، فإن الجمع بين هاتين التقنيتين لإنشاء ربط مشروط للـ Scroll-Timeline بناءً على سياق الحاوية يتطلب فهماً دقيقاً وتطبيقاً ذكياً. يهدف هذا المقال إلى استكشاف هذا التحدي وتقديم حلول عملية.&lt;/p&gt;

&lt;h2 id="what-are-css-container-queries"&gt;ما هي استعلامات حاويات CSS؟&lt;/h2&gt;
&lt;p&gt;تُعد استعلامات حاويات CSS ثورة في تصميم الويب المتجاوب، حيث تسمح للمطورين بتطبيق الأنماط بناءً على حجم أو خصائص الحاوية الأصلية للعنصر، بدلاً من حجم منفذ العرض (viewport) بالكامل. هذا يمنح مرونة غير مسبوقة في تصميم المكونات المستقلة التي تتكيف مع سياقها الخاص.&lt;/p&gt;
&lt;pre data-comment='CSS' data-source='style.css'&gt;&lt;code&gt;.card-container {
  container-type: inline-size;
  container-name: card;
}

@container card (min-width: 400px) {
  .card-title {
    font-size: 1.5rem;
  }
  .card-image {
    display: block;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;تُمكن &lt;code&gt;container-type&lt;/code&gt; و &lt;code&gt;container-name&lt;/code&gt; العنصر من أن يصبح حاوية استعلام، مما يتيح للعناصر الداخلية الاستجابة لتغييراته.&lt;/p&gt;

&lt;h2 id="understanding-scroll-timeline"&gt;فهم Scroll-Timeline&lt;/h2&gt;
&lt;p&gt;تُمكن Scroll-Timeline المطورين من ربط الرسوم المتحركة بتقدم التمرير، مما يفتح الباب أمام تأثيرات تمرير جذابة وسلسة. بدلاً من الاعتماد على التوقيت المستند إلى الوقت، يمكن للرسوم المتحركة أن تبدأ وتتوقف وتتغير سرعتها بناءً على موضع التمرير لعنصر معين أو للمستند بأكمله.&lt;/p&gt;
&lt;pre data-comment='CSS' data-source='style.css'&gt;&lt;code&gt;.animated-element {
  animation: fade-in linear forwards;
  animation-timeline: scroll(root); /* أو scroll(self) */
  animation-range: entry 0% cover 50%;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="the-challenge-conditional-binding"&gt;التحدي: الربط المشروط&lt;/h2&gt;
&lt;p&gt;يكمن التحدي في دمج Scroll-Timeline مع استعلامات الحاويات في أن خصائص Scroll-Timeline (مثل &lt;code&gt;animation-timeline&lt;/code&gt; و &lt;code&gt;animation-range&lt;/code&gt;) تُطبق عادةً بشكل مباشر على العناصر، بينما تُحدد استعلامات الحاويات الأنماط بناءً على سياق الحاوية. قد نرغب في تفعيل تأثير تمرير معين فقط عندما تكون الحاوية كبيرة بما يكفي، أو تعطيله عندما تكون صغيرة لتجنب تشتيت المستخدم أو لتبسيط التجربة.&lt;/p&gt;
&lt;p class='pIndent'&gt;لا توجد آلية مدمجة مباشرة في CSS تسمح بتفعيل أو تعطيل &lt;code&gt;animation-timeline&lt;/code&gt; بشكل مشروط ضمن &lt;code&gt;@container&lt;/code&gt;. هذا يتطلب نهجاً غير مباشر.&lt;/p&gt;

&lt;h2 id="practical-solutions"&gt;حلول عملية للربط المشروط&lt;/h2&gt;

&lt;h3 id="method-1-leveraging-css-variables"&gt;الطريقة الأولى: الاستفادة من متغيرات CSS&lt;/h3&gt;
&lt;p&gt;تُعد متغيرات CSS (Custom Properties) أداة قوية لتمرير القيم ديناميكياً عبر CSS. يمكننا استخدامها لتعيين قيم Scroll-Timeline بشكل مشروط داخل استعلامات الحاويات، ثم استخدام هذه المتغيرات في تعريف الرسوم المتحركة.&lt;/p&gt;
&lt;pre data-comment='CSS' data-source='style.css'&gt;&lt;code&gt;.scroll-container {
  container-type: inline-size;
  container-name: my-container;
  /* القيم الافتراضية أو المعطلة */
  --scroll-timeline-name: none;
  --scroll-timeline-range: auto;
}

@container my-container (min-width: 600px) {
  /* تفعيل Scroll-Timeline عند استيفاء الشرط */
  --scroll-timeline-name: scroll(self);
  --scroll-timeline-range: entry 0% cover 50%;
}

.animated-item {
  animation: slide-in linear forwards;
  animation-timeline: var(--scroll-timeline-name);
  animation-range: var(--scroll-timeline-range);
}

@keyframes slide-in {
  from { transform: translateX(-100%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;في هذا المثال، يتم تعيين &lt;code&gt;--scroll-timeline-name&lt;/code&gt; و &lt;code&gt;--scroll-timeline-range&lt;/code&gt; إلى قيم "معطلة" (&lt;code&gt;none&lt;/code&gt; و &lt;code&gt;auto&lt;/code&gt;) بشكل افتراضي. عند استيفاء شرط &lt;code&gt;@container&lt;/code&gt;، يتم تحديث هذه المتغيرات بقيم Scroll-Timeline المرغوبة، مما يؤدي إلى تفعيل الرسوم المتحركة.&lt;/p&gt;

&lt;h3 id="method-2-conditional-application-of-styles"&gt;الطريقة الثانية: التطبيق المشروط للأنماط الكاملة&lt;/h3&gt;
&lt;p&gt;بدلاً من استخدام المتغيرات، يمكننا تطبيق خصائص Scroll-Timeline بأكملها مباشرة داخل كتلة &lt;code&gt;@container&lt;/code&gt;. هذا النهج أكثر وضوحاً في بعض الحالات.&lt;/p&gt;
&lt;pre data-comment='CSS' data-source='style.css'&gt;&lt;code&gt;.scroll-container {
  container-type: inline-size;
  container-name: my-container;
}

.animated-item {
  /* الأنماط الأساسية */
  opacity: 0; /* مخفي افتراضياً */
  transform: translateY(20px);
  transition: opacity 0.3s, transform 0.3s; /* انتقال سلس عند عدم وجود Scroll-Timeline */
}

@container my-container (min-width: 700px) {
  .animated-item {
    animation: fade-up linear forwards;
    animation-timeline: scroll(self);
    animation-range: entry 0% cover 50%;
    /* إلغاء الانتقال اليدوي عند تفعيل Scroll-Timeline */
    transition: none;
  }
}

@keyframes fade-up {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;هنا، يتم تطبيق الرسوم المتحركة المستندة إلى التمرير فقط عندما تكون الحاوية أكبر من 700 بكسل. عندما تكون الحاوية أصغر، قد نختار إما إخفاء العنصر، أو تطبيق انتقال CSS بسيط، أو عرضه بدون أي تأثير تمرير.&lt;/p&gt;

&lt;h2 id="considerations-and-best-practices"&gt;اعتبارات وأفضل الممارسات&lt;/h2&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;الأداء:&lt;/b&gt; تأكد من أن الرسوم المتحركة خفيفة ولا تسبب مشاكل في الأداء، خاصة على الأجهزة الأقل قوة. اختبر على نطاق واسع.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إمكانية الوصول:&lt;/b&gt; توفير بدائل للرسوم المتحركة أو تعطيلها للمستخدمين الذين يفضلون تقليل الحركة (باستخدام &lt;code&gt;@media (prefers-reduced-motion)&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الدعم المتصفح:&lt;/b&gt; تحقق من دعم المتصفحات لكل من استعلامات الحاويات و Scroll-Timeline. قد تحتاج إلى استخدام polyfills أو تقديم تجارب بديلة للمتصفحات القديمة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التعقيد:&lt;/b&gt; تجنب الإفراط في تعقيد المنطق. كلما كان الحل أبسط، كان أسهل في الصيانة والتصحيح.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class='alert info outline'&gt;
  &lt;p&gt;&lt;b&gt;نصيحة:&lt;/b&gt; عند استخدام &lt;code&gt;scroll(self)&lt;/code&gt;، تأكد من أن العنصر الذي يتم تطبيق الرسوم المتحركة عليه هو نفسه الذي يمكن التمرير فيه، أو أن لديه سلفاً قابلاً للتمرير لكي يعمل الـ timeline بشكل صحيح.&lt;/p&gt;
&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكنني استخدام JavaScript للتحكم في ربط Scroll-Timeline المشروط؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكن استخدام JavaScript لإضافة أو إزالة فئات CSS التي تحتوي على خصائص Scroll-Timeline بناءً على حجم الحاوية أو أي منطق آخر. ومع ذلك، فإن الحلول المستندة إلى CSS (مثل متغيرات CSS أو &lt;code&gt;@container&lt;/code&gt; مباشرة) تُفضل عادةً للبساطة والأداء عندما يكون ذلك ممكناً.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هو الفرق بين &lt;code&gt;scroll(root)&lt;/code&gt; و &lt;code&gt;scroll(self)&lt;/code&gt;؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;&lt;code&gt;scroll(root)&lt;/code&gt; يربط الرسوم المتحركة بتقدم التمرير للمستند بأكمله (عادةً &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; أو &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;). بينما &lt;code&gt;scroll(self)&lt;/code&gt; يربط الرسوم المتحركة بتقدم التمرير للعنصر نفسه أو أقرب سلف قابل للتمرير له. هذا الأخير مفيد جداً للمكونات المعزولة.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/09/css-conditional.html'&gt;ربط Scroll-Timeline المشروط ضمن استعلامات حاويات CSS&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>حل مشكلة req.body غير المعرف في Express.js</title><link>https://www.siwane.xyz/2026/08/express-request-body.html</link><category>مقالات AI</category><pubDate>Mon, 31 Aug 2026 10:27:45 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-2263782135300177564</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="حل مشكلة req.body غير المعرف في Express.js" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;تعرف على الأسباب الشائعة لكون &lt;code&gt;req.body&lt;/code&gt; غير معرف في Express.js وكيفية استخدام &lt;code&gt;express.json()&lt;/code&gt; و &lt;code&gt;express.urlencoded()&lt;/code&gt; لحل المشكلة بفعالية.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; تطوير تطبيقات الويب باستخدام Express.js، قد تواجه مشكلة شائعة حيث تجد أن الكائن &lt;code&gt;req.body&lt;/code&gt; غير معرف (&lt;code&gt;undefined&lt;/code&gt;) عند محاولة الوصول إلى البيانات المرسلة في جسم الطلب (request body). تحدث هذه المشكلة عادةً عندما لا يقوم Express بمعالجة أو تحليل جسم الطلب بشكل صحيح. يهدف هذا المقال إلى تقديم حلول عملية ومباشرة لهذه المشكلة.&lt;/p&gt;

&lt;h2 id="why-req-body-is-undefined"&gt;لماذا يكون &lt;code&gt;req.body&lt;/code&gt; غير معرف؟&lt;/h2&gt;
&lt;p&gt;بشكل افتراضي، لا يقوم Express.js بتحليل جسم الطلب القادم من العميل. هذا يعني أنه إذا أرسل العميل بيانات بتنسيق JSON أو URL-encoded أو أي تنسيق آخر في جسم الطلب، فإن Express لن يتعرف عليها تلقائيًا ولن يملأ الكائن &lt;code&gt;req.body&lt;/code&gt; بها. للوصول إلى هذه البيانات، يجب عليك استخدام middleware مخصص لتحليل جسم الطلب.&lt;/p&gt;

&lt;h2 id="solution-using-express-built-in-middleware"&gt;الحل: استخدام الـ Middleware المدمج في Express&lt;/h2&gt;
&lt;p&gt;الحل الأكثر شيوعًا وفعالية لهذه المشكلة هو استخدام الـ middleware المدمج في Express لتحليل جسم الطلب. Express يوفر دوال مساعدة لهذا الغرض:&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;&lt;code&gt;express.json()&lt;/code&gt;&lt;/b&gt;: لتحليل الطلبات ذات الرأس &lt;code&gt;Content-Type: application/json&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;&lt;code&gt;express.urlencoded()&lt;/code&gt;&lt;/b&gt;: لتحليل الطلبات ذات الرأس &lt;code&gt;Content-Type: application/x-www-form-urlencoded&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="implementing-express-json"&gt;تطبيق &lt;code&gt;express.json()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;إذا كان تطبيقك يتلقى بيانات بتنسيق JSON (وهو الشائع في واجهات برمجة التطبيقات RESTful)، فيجب عليك استخدام &lt;code&gt;express.json()&lt;/code&gt;. قم بإضافته كـ middleware على مستوى التطبيق (global middleware) قبل تعريف مساراتك (routes).&lt;/p&gt;
&lt;pre data-comment='JavaScript' data-source='app.js'&gt;&lt;code&gt;const express = require('express');
const app = express();
const PORT = 3000;

// &lt;mark class='green block' data-before='+'&gt;استخدام middleware لتحليل جسم الطلب بتنسيق JSON&lt;/mark&gt;
&lt;mark class='green block' data-before='+'&gt;app.use(express.json());&lt;/mark&gt;

app.post('/api/data', (req, res) =&gt; {
  // الآن، req.body سيكون متاحًا إذا كان الطلب يحتوي على JSON
  const data = req.body;
  console.log('Received data:', data);

  if (!data || Object.keys(data).length === 0) {
    return res.status(400).send('No data provided in the request body.');
  }

  res.status(200).json({ message: 'Data received successfully!', yourData: data });
});

app.listen(PORT, () =&gt; {
  console.log(`Server running on port ${PORT}`);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;تأكد من أن العميل الذي يرسل الطلب يضبط رأس &lt;code&gt;Content-Type&lt;/code&gt; إلى &lt;code&gt;application/json&lt;/code&gt;. إذا لم يتم ضبطه بشكل صحيح، فلن يتمكن &lt;code&gt;express.json()&lt;/code&gt; من تحليل الجسم.&lt;/p&gt;

&lt;h3 id="implementing-express-urlencoded"&gt;تطبيق &lt;code&gt;express.urlencoded()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;إذا كنت تتعامل مع بيانات مرسلة من نماذج HTML التقليدية (مثل &lt;code&gt;&lt;form method="POST"&gt;&lt;/code&gt;) التي تستخدم ترميز URL (&lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;)، فستحتاج إلى &lt;code&gt;express.urlencoded()&lt;/code&gt;.&lt;/p&gt;
&lt;pre data-comment='JavaScript' data-source='app.js'&gt;&lt;code&gt;const express = require('express');
const app = express();
const PORT = 3000;

// &lt;mark class='green block' data-before='+'&gt;استخدام middleware لتحليل جسم الطلب بتنسيق URL-encoded&lt;/mark&gt;
&lt;mark class='green block' data-before='+'&gt;app.use(express.urlencoded({ extended: true }));&lt;/mark&gt;

app.post('/submit-form', (req, res) =&gt; {
  // الآن، req.body سيكون متاحًا إذا كان الطلب يحتوي على بيانات URL-encoded
  const formData = req.body;
  console.log('Form data:', formData);

  if (!formData || Object.keys(formData).length === 0) {
    return res.status(400).send('No form data provided.');
  }

  res.status(200).send(`Thank you, ${formData.name}! Your email is ${formData.email}.`);
});

app.listen(PORT, () =&gt; {
  console.log(`Server running on port ${PORT}`);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;الخيار &lt;code&gt;{ extended: true }&lt;/code&gt; يسمح بتحليل الكائنات والجداول المتداخلة (nested objects and arrays) من بيانات URL-encoded. يوصى به بشكل عام.&lt;/p&gt;

&lt;h2 id="middleware-order-matters"&gt;ترتيب الـ Middleware مهم&lt;/h2&gt;
&lt;p&gt;من الأهمية بمكان أن تقوم بتسجيل middleware تحليل جسم الطلب (مثل &lt;code&gt;express.json()&lt;/code&gt; أو &lt;code&gt;express.urlencoded()&lt;/code&gt;) &lt;b style='color:var(--linkC)'&gt;قبل&lt;/b&gt; أي مسارات (routes) أو middleware آخر يحاول الوصول إلى &lt;code&gt;req.body&lt;/code&gt;. إذا قمت بتسجيله بعد المسار، فلن يتم تنفيذه للطلبات التي تصل إلى ذلك المسار، وسيظل &lt;code&gt;req.body&lt;/code&gt; غير معرف.&lt;/p&gt;
&lt;pre data-comment='JavaScript' data-source='app.js'&gt;&lt;code&gt;const express = require('express');
const app = express();

// &lt;mark class='green block' data-before='+'&gt;صحيح: middleware قبل المسار&lt;/mark&gt;
app.use(express.json());

app.post('/data', (req, res) =&gt; {
  console.log(req.body); // سيعمل بشكل صحيح
  res.send('OK');
});

// &lt;mark class='red block' data-before='-'&gt;خطأ: middleware بعد المسار&lt;/mark&gt;
// app.post('/another-data', (req, res) =&gt; {
//   console.log(req.body); // سيكون undefined
//   res.send('OK');
// });
// app.use(express.json()); // هذا متأخر جدًا لهذا المسار
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="content-type-header"&gt;التحقق من رأس &lt;code&gt;Content-Type&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;لكي يعمل middleware تحليل جسم الطلب بشكل صحيح، يجب أن يرسل العميل رأس &lt;code&gt;Content-Type&lt;/code&gt; الصحيح في طلبه. على سبيل المثال:&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;لبيانات JSON: &lt;code&gt;Content-Type: application/json&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;لبيانات URL-encoded: &lt;code&gt;Content-Type: application/x-www-form-urlencoded&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;إذا كان رأس &lt;code&gt;Content-Type&lt;/code&gt; مفقودًا أو غير صحيح، فلن يتمكن middleware من تحديد كيفية تحليل جسم الطلب، وسيظل &lt;code&gt;req.body&lt;/code&gt; غير معرف.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
  &lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;
  عند اختبار واجهة برمجة التطبيقات الخاصة بك باستخدام أدوات مثل Postman أو Insomnia أو cURL، تأكد دائمًا من ضبط رأس &lt;code&gt;Content-Type&lt;/code&gt; بشكل صحيح بالإضافة إلى إرسال جسم الطلب.
&lt;/div&gt;

&lt;h2 id="troubleshooting-and-debugging"&gt;استكشاف الأخطاء وإصلاحها&lt;/h2&gt;
&lt;p&gt;إذا كنت لا تزال تواجه مشكلة، جرب الخطوات التالية:&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;تحقق من الـ Middleware&lt;/b&gt;: تأكد من أنك قمت بتضمين &lt;code&gt;app.use(express.json());&lt;/code&gt; و/أو &lt;code&gt;app.use(express.urlencoded({ extended: true }));&lt;/code&gt; في ملف التطبيق الرئيسي الخاص بك.&lt;/li&gt;
  &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;تحقق من الترتيب&lt;/b&gt;: تأكد من أن الـ middleware هذا يقع قبل أي مسارات تحاول الوصول إلى &lt;code&gt;req.body&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;تحقق من رأس &lt;code&gt;Content-Type&lt;/code&gt;&lt;/b&gt;: استخدم أدوات المطور في المتصفح أو أدوات مثل Postman للتحقق من أن رأس &lt;code&gt;Content-Type&lt;/code&gt; يتم إرساله بشكل صحيح من العميل.&lt;/li&gt;
  &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;سجل &lt;code&gt;req&lt;/code&gt; بالكامل&lt;/b&gt;: قبل الوصول إلى &lt;code&gt;req.body&lt;/code&gt;، قم بتسجيل الكائن &lt;code&gt;req&lt;/code&gt; بالكامل أو &lt;code&gt;req.headers&lt;/code&gt; و &lt;code&gt;req.method&lt;/code&gt; و &lt;code&gt;req.url&lt;/code&gt; للتحقق من أن الطلب يصل كما هو متوقع.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="conclusion"&gt;الخلاصة&lt;/h2&gt;
&lt;p&gt;مشكلة &lt;code&gt;req.body&lt;/code&gt; غير المعرف في Express.js هي مشكلة شائعة ولكن حلها بسيط. من خلال فهم أن Express لا يقوم بتحليل جسم الطلب افتراضيًا واستخدام الـ middleware المناسب مثل &lt;code&gt;express.json()&lt;/code&gt; و &lt;code&gt;express.urlencoded()&lt;/code&gt;، يمكنك الوصول بسهولة إلى البيانات المرسلة من العميل. تذكر دائمًا أهمية ترتيب الـ middleware والتحقق من رأس &lt;code&gt;Content-Type&lt;/code&gt; لضمان سير عمل سلس لتطبيقك.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل أحتاج إلى تثبيت حزمة &lt;code&gt;body-parser&lt;/code&gt; بشكل منفصل؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;لا، بدءًا من Express 4.16.0، تم تضمين وظائف &lt;code&gt;body-parser&lt;/code&gt; (مثل &lt;code&gt;json()&lt;/code&gt; و &lt;code&gt;urlencoded()&lt;/code&gt;) مباشرة في Express نفسه. لذلك، لا تحتاج إلى تثبيت &lt;code&gt;body-parser&lt;/code&gt; كحزمة منفصلة بعد الآن.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ماذا لو كنت أرسل بيانات متعددة الأجزاء (multipart/form-data)؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;إذا كنت ترسل بيانات متعددة الأجزاء (عادةً لرفع الملفات)، فإن &lt;code&gt;express.json()&lt;/code&gt; و &lt;code&gt;express.urlencoded()&lt;/code&gt; لن تكون كافية. ستحتاج إلى استخدام middleware متخصص مثل &lt;a class='extL' href='https://github.com/expressjs/multer' rel='nofollow noreferrer' target='_blank'&gt;Multer&lt;/a&gt; لمعالجة هذا النوع من الطلبات.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/08/express-request-body.html'&gt;حل مشكلة &lt;code&gt;req.body&lt;/code&gt; غير المعرف في Express.js&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>احتراف GitHub: دليلك الشامل لأحدث التطورات</title><link>https://www.siwane.xyz/2026/09/mastering.html</link><category>مقالات AI</category><pubDate>Mon, 7 Sep 2026 10:27:50 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-5735183770855333138</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="احتراف GitHub: دليلك الشامل لأحدث التطورات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;دليلك الشامل لاحتراف GitHub، بدءًا من الأساسيات وصولاً إلى أحدث الابتكارات مثل GitHub Actions وCodespaces وCopilot، مع نصائح عملية.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;يُعد GitHub المنصة الرائدة عالميًا للتحكم في إصدار التعليمات البرمجية والتعاون بين المطورين. احترافه لم يعد خيارًا، بل ضرورة لكل مطور يسعى للتميز في عالم البرمجيات الحديث. يهدف هذا المقال إلى تقديم خارطة طريق عملية لاحتراف GitHub، مع تسليط الضوء على أبرز التطورات التي غيرت طريقة عملنا.&lt;/p&gt;

&lt;h2 id="what-is-github"&gt;ما هو GitHub؟&lt;/h2&gt;
&lt;p&gt;GitHub هو خدمة استضافة لمستودعات Git، مبنية على نظام التحكم في الإصدار الموزع (Git). يسمح للمطورين بالتعاون في المشاريع من أي مكان في العالم، وتتبع التغييرات، وإدارة الإصدارات المختلفة للتعليمات البرمجية. إنه ليس مجرد مكان لتخزين الكود، بل هو نظام بيئي كامل يدعم دورة حياة تطوير البرمجيات.&lt;/p&gt;

&lt;h2 id="core-concepts"&gt;المفاهيم الأساسية لاحتراف GitHub&lt;/h2&gt;
&lt;p&gt;لتبدأ رحلة الاحتراف، يجب أولاً فهم وتطبيق المفاهيم الأساسية لـ Git وGitHub:&lt;/p&gt;

&lt;h3 id="repositories"&gt;المستودعات (Repositories)&lt;/h3&gt;
&lt;p&gt;المستودع هو المجلد الرئيسي لمشروعك، حيث يتم تخزين جميع ملفات المشروع وسجل التغييرات. تعلم كيفية إنشاء مستودعات جديدة (عامة وخاصة) واستنساخ (&lt;code&gt;git clone&lt;/code&gt;) المستودعات الموجودة هو الخطوة الأولى.&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git clone&lt;/mark&gt; https://github.com/user/repo.git&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="branches"&gt;الفروع (Branches)&lt;/h3&gt;
&lt;p&gt;الفروع تسمح لك بالعمل على ميزات جديدة أو إصلاح الأخطاء بمعزل عن الكود الرئيسي (&lt;code&gt;main&lt;/code&gt; أو &lt;code&gt;master&lt;/code&gt;). احتراف إدارة الفروع (إنشاء، التبديل، الدمج) أمر بالغ الأهمية لسير عمل فعال.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;إنشاء فرع جديد: &lt;code&gt;&lt;mark class='green' data-before='$'&gt;git branch&lt;/mark&gt; feature-x&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;التبديل إلى الفرع: &lt;code&gt;&lt;mark class='green' data-before='$'&gt;git checkout&lt;/mark&gt; feature-x&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;إنشاء والتبديل مباشرة: &lt;code&gt;&lt;mark class='green' data-before='$'&gt;git checkout -b&lt;/mark&gt; feature-x&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="commits"&gt;الالتزامات (Commits)&lt;/h3&gt;
&lt;p&gt;الالتزام هو لقطة للتغييرات التي أجريتها في نقطة زمنية معينة. اكتب رسائل التزام واضحة وموجزة تصف التغييرات بدقة. هذا يسهل تتبع تاريخ المشروع وفهم التغييرات لاحقًا.&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code&gt;&lt;mark class='green' data-before='$'&gt;git add&lt;/mark&gt; .&lt;br/&gt;&lt;mark class='green' data-before='$'&gt;git commit -m&lt;/mark&gt; "أضف ميزة تسجيل الدخول"&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="pull-requests"&gt;طلبات السحب (Pull Requests - PRs)&lt;/h3&gt;
&lt;p&gt;طلبات السحب هي قلب التعاون في GitHub. تسمح لك باقتراح دمج التغييرات من فرعك إلى فرع آخر (عادةً &lt;code&gt;main&lt;/code&gt;). تعلم كيفية إنشاء PRs فعالة، ومراجعة كود الآخرين، والتعامل مع التعليقات والتعديلات.&lt;/p&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;PRs ليست فقط لدمج الكود؛ إنها فرصة للمراجعة، المناقشة، وتحسين جودة الكود.&lt;/p&gt;

&lt;h3 id="forking"&gt;النسخ المتفرع (Forking)&lt;/h3&gt;
&lt;p&gt;النسخ المتفرع هو إنشاء نسخة شخصية من مستودع شخص آخر على حسابك. هذا مفيد للمساهمة في مشاريع مفتوحة المصدر دون التأثير مباشرة على المستودع الأصلي.&lt;/p&gt;

&lt;h2 id="advanced-features"&gt;أحدث التطورات والميزات المتقدمة في GitHub&lt;/h2&gt;
&lt;p&gt;للانتقال من مستوى المبتدئ إلى المحترف، يجب استكشاف واستخدام الميزات المتقدمة التي يقدمها GitHub:&lt;/p&gt;

&lt;h3 id="github-actions"&gt;GitHub Actions&lt;/h3&gt;
&lt;p&gt;تُعد GitHub Actions أداة قوية لأتمتة مهام سير العمل (CI/CD) مباشرة داخل مستودعك. يمكنك بناء، اختبار، ونشر تطبيقك تلقائيًا عند كل التزام أو طلب سحب. احترافها يقلل من الأخطاء البشرية ويسرع عملية التطوير.&lt;/p&gt;
&lt;pre data-comment='YAML' data-source='.github/workflows/main.yml'&gt;&lt;code&gt;name: CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '16'
    - name: Install dependencies
      run: npm install
    - name: Run tests
      run: npm test&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="github-packages"&gt;GitHub Packages&lt;/h3&gt;
&lt;p&gt;تسمح لك GitHub Packages باستضافة حزم البرمجيات الخاصة بك (مثل npm، Maven، NuGet) مباشرة على GitHub. هذا يبسط إدارة التبعيات ويوفر حلاً موحدًا لاستضافة الكود والحزم.&lt;/p&gt;

&lt;h3 id="github-codespaces"&gt;GitHub Codespaces&lt;/h3&gt;
&lt;p&gt;Codespaces يوفر بيئة تطوير متكاملة (IDE) قائمة على السحابة، يمكن الوصول إليها مباشرة من متصفحك. يتيح لك بدء العمل على مشروعك في ثوانٍ، دون الحاجة إلى إعداد بيئة محلية معقدة. إنه يغير قواعد اللعبة للتعاون السريع والانضمام إلى المشاريع.&lt;/p&gt;

&lt;h3 id="github-copilot"&gt;GitHub Copilot&lt;/h3&gt;
&lt;p&gt;مدعومًا بالذكاء الاصطناعي، يقدم Copilot اقتراحات للكود في الوقت الفعلي أثناء الكتابة. يمكنه تسريع عملية الترميز بشكل كبير، خاصة للمهام المتكررة أو عند العمل بلغات وأطر عمل جديدة. تعلم كيفية الاستفادة منه لتحسين إنتاجيتك.&lt;/p&gt;

&lt;h3 id="security-features"&gt;ميزات الأمان المتقدمة&lt;/h3&gt;
&lt;p&gt;يقدم GitHub مجموعة من الأدوات لتعزيز أمان الكود، مثل &lt;b style='color:var(--linkC)'&gt;Dependabot&lt;/b&gt; الذي يقوم بفحص التبعيات بحثًا عن الثغرات الأمنية وتحديثها تلقائيًا، و&lt;b style='color:var(--linkC)'&gt;Code Scanning&lt;/b&gt; الذي يكتشف المشكلات الأمنية المحتملة في الكود الخاص بك.&lt;/p&gt;

&lt;h2 id="practical-mastery"&gt;خطوات عملية لاحتراف GitHub&lt;/h2&gt;

&lt;h3 id="hands-on-practice"&gt;الممارسة العملية المستمرة&lt;/h3&gt;
&lt;p&gt;لا يمكن احتراف GitHub بالقراءة فقط. قم بإنشاء مشاريع شخصية، جرب جميع الأوامر والميزات، وادفع الكود بانتظام. كلما زادت ممارستك، زادت ثقتك ومهارتك.&lt;/p&gt;

&lt;h3 id="open-source-contribution"&gt;المساهمة في المشاريع مفتوحة المصدر&lt;/h3&gt;
&lt;p&gt;المساهمة في المشاريع مفتوحة المصدر هي أفضل طريقة لتطبيق ما تعلمته في بيئة حقيقية. ستتعلم كيفية العمل ضمن فرق، ومراجعة الكود، والتعامل مع سير عمل PRs المعقدة.&lt;/p&gt;

&lt;h3 id="stay-updated"&gt;البقاء على اطلاع دائم&lt;/h3&gt;
&lt;p&gt;GitHub يتطور باستمرار. تابع المدونة الرسمية لـ GitHub، وحضر الندوات عبر الإنترنت، واقرأ عن الميزات الجديدة فور إطلاقها. هذا يضمن أنك دائمًا في طليعة التطورات.&lt;/p&gt;

&lt;div class='alert info outline'&gt;
  &lt;p&gt;&lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;استخدم &lt;a class='extL' href='https://docs.github.com/en/get-started/quickstart/set-up-git' rel='nofollow noreferrer' target='_blank'&gt;وثائق GitHub الرسمية&lt;/a&gt; كمصدر أساسي للتعلم. إنها شاملة ومحدثة باستمرار.&lt;/p&gt;
&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل أحتاج إلى معرفة Git قبل استخدام GitHub؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، GitHub مبني على Git. فهم أساسيات Git (مثل الالتزامات، الفروع، الدمج) ضروري لاستخدام GitHub بفعالية.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين GitHub و GitLab؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;كلاهما منصات لاستضافة مستودعات Git، لكن GitLab يركز بشكل أكبر على دورة حياة DevOps الكاملة، بما في ذلك CI/CD المدمج، في حين أن GitHub كان يركز تقليديًا على استضافة الكود والتعاون، ولكنه توسع بشكل كبير في DevOps مؤخرًا مع GitHub Actions وCodespaces.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/09/mastering.html'&gt;احتراف GitHub: دليلك الشامل لأحدث التطورات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>تحويل وسم hr  إلى تحفة فنية: دمج SVG المتكرر كفاصل مرئي</title><link>https://www.siwane.xyz/2026/08/svg-loop.html</link><category>مقالات AI</category><pubDate>Mon, 24 Aug 2026 10:28:00 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-4395432323948454909</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="تحويل وسم hr إلى تحفة فنية: دمج SVG المتكرر كفاصل مرئي" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف كيفية استبدال عنصر &lt;hr /&gt; التقليدي برسوم SVG متكررة لإنشاء فواصل مرئية ديناميكية وجذابة، مع أمثلة عملية.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تصميم الويب الحديث، لم يعد الاكتفاء بالعناصر الافتراضية للمتصفح خياراً جذاباً. عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;hr /&amp;gt;&lt;/b&gt;، الذي يُستخدم تقليدياً لإنشاء فاصل أفقي، غالباً ما يفتقر إلى المرونة الجمالية. لحسن الحظ، توفر رسوم SVG (Scalable Vector Graphics) حلاً قوياً ومبتكراً لتحويل هذا الفاصل البسيط إلى عنصر تصميم جذاب ومتكرر، يتماشى مع هوية موقعك البصرية.&lt;/p&gt;

&lt;h2 id="what-is-svg-and-why"&gt;ما هو SVG ولماذا نستخدمه؟&lt;/h2&gt;
&lt;p&gt;SVG هو تنسيق صور قائم على XML للرسومات المتجهة ثنائية الأبعاد. على عكس الصور النقطية (مثل JPG أو PNG)، لا تفقد رسوم SVG جودتها عند تكبيرها أو تصغيرها، مما يجعلها مثالية للاستخدام في تصميم الويب سريع الاستجابة. عند استخدام SVG كفاصل مرئي، يمكننا تحقيق تصاميم معقدة وديناميكية لا يمكن تحقيقها بسهولة باستخدام CSS وحده أو صور نقطية.&lt;/p&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يمكن تضمين رسوم SVG مباشرة في HTML أو CSS، مما يقلل من طلبات HTTP ويحسن أداء التحميل.&lt;/p&gt;

&lt;h2 id="hr-limitations"&gt;قيود &lt;hr /&gt; التقليدية والحاجة للبديل&lt;/h2&gt;
&lt;p&gt;بشكل افتراضي، يظهر عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;hr /&amp;gt;&lt;/b&gt; كخط أفقي رفيع، يختلف مظهره قليلاً بين المتصفحات. على الرغم من إمكانية تعديل بعض خصائصه الأساسية مثل اللون والارتفاع باستخدام CSS، إلا أن تحقيق أنماط معقدة أو متكررة يتطلب تجاوز قدراته المحدودة. هنا يأتي دور SVG لتقديم حلول تصميم لا نهائية، من الخطوط المتموجة إلى الأنماط الهندسية المتكررة.&lt;/p&gt;

&lt;h2 id="designing-svg-separator"&gt;تصميم SVG لفاصل مرئي متكرر&lt;/h2&gt;
&lt;p&gt;يكمن سر استخدام SVG كفاصل متكرر في إنشاء نمط صغير يمكن تكراره أفقياً (أو رأسياً). لنفترض أننا نريد إنشاء فاصل بنمط "نقاط متقطعة". يمكننا تصميم جزء صغير من هذا النمط في SVG.&lt;/p&gt;
&lt;pre data-comment='SVG' data-source='dot-pattern.svg'&gt;&lt;code&gt;&amp;lt;svg width="10" height="2" viewBox="0 0 10 2" xmlns="http://www.w3.org/2000/svg"&amp;gt;
  &amp;lt;circle cx="1" cy="1" r="1" fill="#888" /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;في هذا المثال، أنشأنا SVG بعرض 10 بكسل وارتفاع 2 بكسل يحتوي على دائرة صغيرة. عند تكرار هذا النمط، سيبدو كخط من النقاط المتباعدة.&lt;/p&gt;

&lt;h2 id="applying-looping-svg"&gt;تطبيق SVG المتكرر كخلفية&lt;/h2&gt;
&lt;p&gt;لتحويل SVG إلى فاصل مرئي متكرر، سنستخدم خاصية &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;background-image&lt;/code&gt;&lt;/b&gt; في CSS، مع تضمين SVG مباشرة كـ &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;data:image/svg+xml&lt;/code&gt;&lt;/b&gt;. هذا يضمن أن المتصفح يقوم بتحميل SVG كصورة خلفية ويقوم بتكرارها.&lt;/p&gt;

&lt;h2 id="practical-implementation-steps"&gt;خطوات التنفيذ العملي&lt;/h2&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;الخطوة 1: إعداد عنصر &amp;lt;hr /&amp;gt; في HTML&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;نبدأ بعنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;hr /&amp;gt;&lt;/b&gt; بسيط في ملف HTML الخاص بك:&lt;/p&gt;
    &lt;pre data-comment='HTML' data-source='index.html'&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="ar"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;title&amp;gt;SVG HR Example&amp;lt;/title&amp;gt;
    &amp;lt;link rel="stylesheet" href="style.css"&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;مقال حول SVG كفاصل &amp;lt;hr /&amp;gt;&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;هذا نص قبل الفاصل.&amp;lt;/p&amp;gt;
    &amp;lt;hr /&amp;gt;
    &amp;lt;p&amp;gt;هذا نص بعد الفاصل.&amp;lt;/p&amp;gt;
    &amp;lt;hr class="dots" /&amp;gt;
    &amp;lt;p&amp;gt;فاصل بنقاط.&amp;lt;/p&amp;gt;
    &amp;lt;hr class="wave" /&amp;gt;
    &amp;lt;p&amp;gt;فاصل بموجة.&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;الخطوة 2: تصميم SVG للنمط&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;سنستخدم نمطاً بسيطاً من الخطوط المائلة المتكررة. يمكن تحويل هذا SVG إلى تنسيق URL لسهولة تضمينه في CSS.&lt;/p&gt;
    &lt;pre data-comment='SVG Pattern' data-source='pattern.svg'&gt;&lt;code&gt;&amp;lt;svg width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"&amp;gt;
  &amp;lt;line x1="0" y1="10" x2="10" y2="0" stroke="#ccc" stroke-width="1" /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;هذا النمط سيخلق خطوطاً مائلة متكررة. يمكن تعديل &lt;code&gt;stroke&lt;/code&gt; و &lt;code&gt;stroke-width&lt;/code&gt; لتغيير اللون والسماكة.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;الخطوة 3: تطبيق CSS على &amp;lt;hr /&amp;gt;&lt;/b&gt;&lt;/p&gt;
    &lt;p&gt;الآن، سنقوم بتطبيق النمط على عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;hr /&amp;gt;&lt;/b&gt; باستخدام CSS. سنقوم بإزالة الحدود الافتراضية وتعيين SVG كخلفية متكررة.&lt;/p&gt;
    &lt;pre data-comment='CSS' data-source='style.css'&gt;&lt;code&gt;hr {
    border: none; /* إزالة الحدود الافتراضية */
    height: 10px; /* تحديد ارتفاع الفاصل ليتناسب مع ارتفاع SVG */
    background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cline x1='0' y1='10' x2='10' y2='0' stroke='%23ccc' stroke-width='1' /%3E%3C/svg%3E");
    background-repeat: repeat-x; /* تكرار النمط أفقياً */
    background-size: 10px 10px; /* حجم النمط الواحد */
    margin: 2em 0; /* مسافة أعلى وأسفل الفاصل */
}
/* مثال على نمط آخر: نقاط */
hr.dots {
    height: 2px;
    background-image: url("data:image/svg+xml,%3Csvg width='10' height='2' viewBox='0 0 10 2' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='1' cy='1' r='1' fill='%23888' /%3E%3C/svg%3E");
    background-repeat: repeat-x;
    background-size: 10px 2px;
}
/* مثال على نمط آخر: موجة */
hr.wave {
    height: 20px;
    background-image: url("data:image/svg+xml,%3Csvg width='40' height='20' viewBox='0 0 40 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 10 Q10 0 20 10 T40 10' stroke='%23f00' fill='none' stroke-width='2'/%3E%3C/svg%3E");
    background-repeat: repeat-x;
    background-size: 40px 20px;
}
&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='pIndent'&gt;لاحظ أننا قمنا بترميز SVG ليكون آمناً للاستخدام في URL. يمكن استخدام أدوات عبر الإنترنت لترميز SVG إلى URL إذا كان النمط معقداً.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class='alert info outline'&gt;
    &lt;p&gt;&lt;b&gt;نصيحة:&lt;/b&gt; لإنشاء أنماط SVG معقدة، يمكنك تصميمها في محرر رسومي مثل Adobe Illustrator أو Inkscape، ثم تصديرها كـ SVG. بعد ذلك، قم بتحسين الكود وإزالة أي عناصر غير ضرورية قبل ترميزها لـ CSS.&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id="accessibility-considerations"&gt;اعتبارات إمكانية الوصول&lt;/h2&gt;
&lt;p&gt;عند استبدال &lt;b style='color:var(--linkC)'&gt;&amp;lt;hr /&amp;gt;&lt;/b&gt; برسوم SVG، من المهم التأكد من أن الفاصل لا يزال ينقل المعنى الدلالي الصحيح إذا كان ذلك مطلوباً. إذا كان الفاصل مجرد عنصر تزييني، فلا بأس. ولكن إذا كان يمثل فاصل محتوى ذا معنى، فتأكد من أن القارئات الشاشة لا تتجاهله تماماً. يمكن إضافة &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;aria-hidden="true"&lt;/code&gt;&lt;/b&gt; إذا كان تزيينياً بحتاً، أو استخدام &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;role="separator"&lt;/code&gt;&lt;/b&gt; إذا كان له معنى دلالي.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;كيف يمكنني جعل SVG المتكرر مستجيباً؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;بما أننا نستخدم SVG كصورة خلفية، فإن استجابته تعتمد على كيفية تحديد &lt;code&gt;background-size&lt;/code&gt;. إذا استخدمت وحدات نسبية مثل &lt;code&gt;%&lt;/code&gt; أو &lt;code&gt;vw&lt;/code&gt; لـ &lt;code&gt;background-size&lt;/code&gt;، فسيتكيف النمط مع حجم العنصر الأب. تأكد أيضاً من أن &lt;code&gt;height&lt;/code&gt; الخاص بـ &lt;code&gt;hr&lt;/code&gt; يتكيف مع الشاشات المختلفة باستخدام استعلامات الوسائط (Media Queries).&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكنني تحريك SVG المستخدم كفاصل؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكن تحريك رسوم SVG باستخدام CSS Animations أو JavaScript. ومع ذلك، عند استخدامها كـ &lt;code&gt;background-image&lt;/code&gt;، تكون خيارات التحريك محدودة. لتحريك النمط نفسه، ستحتاج إلى تضمين SVG مباشرة في HTML واستخدام CSS أو JavaScript لتحريك مساراته أو أشكاله، أو استخدام &lt;code&gt;@keyframes&lt;/code&gt; مع &lt;code&gt;background-position&lt;/code&gt; لإنشاء تأثير تمرير.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/08/svg-loop.html'&gt;تحويل &amp;lt;hr /&amp;gt; إلى تحفة فنية: دمج SVG المتكرر كفاصل مرئي&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>احتراف Docker: دليلك العملي لأحدث التطورات</title><link>https://www.siwane.xyz/2026/08/master_0188411957.html</link><category>مقالات AI</category><pubDate>Mon, 17 Aug 2026 10:27:52 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-2415295614114589527</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="احتراف Docker: دليلك العملي لأحدث التطورات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف كيف تتقن Docker من الأساسيات إلى التقنيات المتقدمة، وتعرّف على أحدث الميزات التي تعزز كفاءة تطويرك ونشر تطبيقاتك.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير البرمجيات الحديث، أصبح &lt;b style='color:var(--linkC)'&gt;Docker&lt;/b&gt; أداة لا غنى عنها لتبسيط عملية بناء التطبيقات ونشرها وإدارتها. يتيح Docker للمطورين تغليف تطبيقاتهم مع جميع تبعياتها في "حاويات" (Containers) خفيفة الوزن وقابلة للنقل، مما يضمن تشغيلها بشكل متسق عبر أي بيئة. هذا المقال يرشدك نحو احتراف Docker ويستعرض أبرز التطورات الحديثة.&lt;/p&gt;

&lt;h2 id="what-is-docker"&gt;ما هو Docker ولماذا هو ضروري؟&lt;/h2&gt;
&lt;p&gt;Docker هو منصة مفتوحة المصدر لأتمتة نشر التطبيقات كحاويات محمولة ومستقلة. يحل مشكلة "يعمل على جهازي" (It works on my machine) من خلال توفير بيئة تشغيل موحدة. تكمن أهميته في:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;التناسق:&lt;/b&gt; يضمن تشغيل التطبيق بنفس الطريقة في بيئات التطوير، الاختبار، والإنتاج.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;العزل:&lt;/b&gt; كل حاوية تعمل في بيئتها المعزولة، مما يمنع تضارب التبعيات.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;السرعة والكفاءة:&lt;/b&gt; بدء تشغيل الحاويات أسرع بكثير من الأجهزة الافتراضية، وتستهلك موارد أقل.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;قابلية النقل:&lt;/b&gt; يمكن نقل الحاويات بسهولة بين الخوادم السحابية أو المحلية.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="foundational-concepts"&gt;المفاهيم الأساسية لاحتراف Docker&lt;/h2&gt;
&lt;p&gt;لإتقان Docker، يجب فهم هذه اللبنات الأساسية:&lt;/p&gt;

&lt;h3 id="dockerfiles"&gt;ملفات Dockerfile&lt;/h3&gt;
&lt;p&gt;هي نصوص برمجية تحتوي على تعليمات لبناء صورة Docker (Docker Image). كل سطر يمثل طبقة (Layer) في الصورة. احترافها يعني كتابة ملفات Dockerfile فعالة ومحسّنة.&lt;/p&gt;
&lt;pre data-comment='Dockerfile' data-source='Dockerfile'&gt;&lt;code&gt;&lt;mark class='green block' data-before='FROM '&gt;python:3.9-slim&lt;/mark&gt;
&lt;mark class='green block' data-before='WORKDIR '&gt;/app&lt;/mark&gt;
&lt;mark class='green block' data-before='COPY '&gt;requirements.txt .&lt;/mark&gt;
&lt;mark class='green block' data-before='RUN '&gt;pip install -r requirements.txt&lt;/mark&gt;
&lt;mark class='green block' data-before='COPY '&gt;. .&lt;/mark&gt;
&lt;mark class='green block' data-before='CMD '&gt;["python", "app.py"]&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;استخدم صورًا أساسية صغيرة (مثل &lt;code&gt;-slim&lt;/code&gt; أو &lt;code&gt;alpine&lt;/code&gt;) لتقليل حجم الصور النهائية.&lt;/p&gt;

&lt;h3 id="images-containers"&gt;الصور والحاويات&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;الصور (Images):&lt;/b&gt; قوالب للقراءة فقط تحتوي على التطبيق وجميع تبعياته. تُبنى من ملفات Dockerfile.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الحاويات (Containers):&lt;/b&gt; نسخ قابلة للتشغيل من الصور. هي المثيل الحي للتطبيق.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;أوامر أساسية: &lt;code&gt;docker build&lt;/code&gt; لبناء الصور، &lt;code&gt;docker run&lt;/code&gt; لتشغيل الحاويات، &lt;code&gt;docker ps&lt;/code&gt; لعرض الحاويات قيد التشغيل.&lt;/p&gt;

&lt;h3 id="volumes-networking"&gt;المجلدات والشبكات&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;المجلدات (Volumes):&lt;/b&gt; تُستخدم لتخزين البيانات المستمرة خارج الحاوية، مما يضمن بقاء البيانات حتى بعد حذف الحاوية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الشبكات (Networking):&lt;/b&gt; تسمح للحاويات بالتواصل مع بعضها البعض ومع العالم الخارجي. Docker يوفر عدة أنماط شبكات (bridge, host, overlay).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="advanced-techniques"&gt;تقنيات Docker المتقدمة&lt;/h2&gt;

&lt;h3 id="docker-compose"&gt;Docker Compose&lt;/h3&gt;
&lt;p&gt;أداة لتعريف وتشغيل تطبيقات Docker متعددة الحاويات. باستخدام ملف YAML واحد، يمكنك تكوين جميع الخدمات والشبكات والمجلدات اللازمة لتطبيقك.&lt;/p&gt;
&lt;pre data-comment='YAML' data-source='docker-compose.yml'&gt;&lt;code&gt;&lt;mark class='green block' data-before='version: '&gt;"3.8"&lt;/mark&gt;
&lt;mark class='green block' data-before='services:'&gt;
  web:&lt;/mark&gt;
    &lt;mark class='green block' data-before='build: '&gt;.&lt;/mark&gt;
    &lt;mark class='green block' data-before='ports:'&gt;
      - "8000:8000"&lt;/mark&gt;
    &lt;mark class='green block' data-before='volumes:'&gt;
      - .:/app&lt;/mark&gt;
    &lt;mark class='green block' data-before='depends_on:'&gt;
      - db&lt;/mark&gt;
  &lt;mark class='green block' data-before='db:'&gt;
    image: postgres:13&lt;/mark&gt;
    &lt;mark class='green block' data-before='environment:'&gt;
      POSTGRES_DB: mydatabase
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;الأمر &lt;code&gt;docker-compose up&lt;/code&gt; يشغل جميع الخدمات المحددة.&lt;/p&gt;

&lt;h3 id="orchestration"&gt;أدوات الأوركسترا (Swarm/Kubernetes)&lt;/h3&gt;
&lt;p&gt;لإدارة ونشر الحاويات على نطاق واسع في بيئات الإنتاج، تُستخدم أدوات الأوركسترا. Docker Swarm هو حل Docker الأصلي، بينما &lt;b style='color:var(--linkC)'&gt;Kubernetes&lt;/b&gt; هو المعيار الصناعي لإدارة مجموعات الحاويات المعقدة.&lt;/p&gt;

&lt;h3 id="multi-stage-builds"&gt;البناء متعدد المراحل (Multi-stage Builds)&lt;/h3&gt;
&lt;p&gt;تقنية لتقليل حجم صور Docker النهائية بشكل كبير. تسمح لك باستخدام مراحل بناء مختلفة، حيث يتم التخلص من الأدوات والتبعيات غير الضرورية في الصورة النهائية.&lt;/p&gt;
&lt;pre data-comment='Dockerfile' data-source='Dockerfile'&gt;&lt;code&gt;&lt;mark class='green block' data-before='FROM '&gt;node:16-alpine AS builder&lt;/mark&gt;
&lt;mark class='green block' data-before='WORKDIR '&gt;/app&lt;/mark&gt;
&lt;mark class='green block' data-before='COPY '&gt;package*.json ./&lt;/mark&gt;
&lt;mark class='green block' data-before='RUN '&gt;npm install&lt;/mark&gt;
&lt;mark class='green block' data-before='COPY '&gt;. .&lt;/mark&gt;
&lt;mark class='green block' data-before='RUN '&gt;npm run build&lt;/mark&gt;

&lt;mark class='green block' data-before='FROM '&gt;nginx:alpine&lt;/mark&gt;
&lt;mark class='green block' data-before='COPY '&gt;--from=builder /app/build /usr/share/nginx/html&lt;/mark&gt;
&lt;mark class='green block' data-before='EXPOSE '&gt;80&lt;/mark&gt;
&lt;mark class='green block' data-before='CMD '&gt;["nginx", "-g", "daemon off;"]&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="latest-developments"&gt;أحدث التطورات في Docker&lt;/h2&gt;

&lt;h3 id="buildkit"&gt;BuildKit&lt;/h3&gt;
&lt;p&gt;محرك بناء أسرع وأكثر كفاءة لـ Docker. يقدم ميزات مثل التخزين المؤقت الذكي، البناء المتوازي، ودعم بناء الصور متعددة المنصات. يتم تمكينه افتراضيًا في الإصدارات الحديثة من Docker.&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code&gt;&lt;mark class='green block' data-before='DOCKER_BUILDKIT=1 docker build -t myapp .'&gt;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="dev-containers"&gt;حاويات التطوير (Dev Containers) وتحسينات Docker Desktop&lt;/h3&gt;
&lt;p&gt;تتيح لك Dev Containers (مدعومة في VS Code و Docker Desktop) تحديد بيئة تطوير كاملة داخل حاوية Docker. هذا يضمن أن كل مطور يعمل في نفس البيئة الموحدة، مما يقلل من مشكلات التوافق. كما أن Docker Desktop يستمر في إضافة ميزات جديدة لتبسيط تجربة المطور.&lt;/p&gt;

&lt;h3 id="security-best-practices"&gt;أفضل ممارسات الأمان&lt;/h3&gt;
&lt;p&gt;الأمان أصبح محور اهتمام كبير. تشمل التطورات التركيز على:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;صور أساسية موثوقة:&lt;/b&gt; استخدام صور من مصادر رسمية ومعروفة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;فحص الثغرات:&lt;/b&gt; أدوات مثل Docker Scout و Trivy لفحص الصور بحثًا عن الثغرات الأمنية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;مبدأ الامتياز الأقل:&lt;/b&gt; تشغيل الحاويات كمستخدمين غير جذريين (non-root) وتقليل الأذونات.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="practical-mastery-tips"&gt;نصائح عملية لاحتراف Docker&lt;/h2&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;الممارسة المستمرة:&lt;/b&gt; قم ببناء مشاريعك الخاصة باستخدام Docker، وجرب سيناريوهات مختلفة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التعمق في الوثائق الرسمية:&lt;/b&gt; &lt;a class='extL' href='https://docs.docker.com/' rel='nofollow noreferrer' target='_blank'&gt;وثائق Docker الرسمية&lt;/a&gt; هي المصدر الأفضل والأكثر دقة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;فهم مبادئ Linux:&lt;/b&gt; بما أن Docker يعتمد على نواة Linux، فإن فهم أساسياتها سيعزز فهمك لعمل الحاويات.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;المشاركة في المجتمع:&lt;/b&gt; انضم إلى منتديات Docker والمجموعات عبر الإنترنت لتبادل الخبرات وحل المشكلات.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تجربة أدوات الأوركسترا:&lt;/b&gt; ابدأ بـ Docker Compose ثم انتقل إلى Kubernetes لفهم إدارة الحاويات على نطاق واسع.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;تجنب تشغيل الحاويات بامتيازات جذرية (root) ما لم يكن ذلك ضروريًا للغاية، لتقليل المخاطر الأمنية.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;خاتمة&lt;/h2&gt;
&lt;p&gt;احتراف Docker هو رحلة مستمرة تتطلب الفهم العميق للمفاهيم الأساسية، والممارسة العملية للتقنيات المتقدمة، ومواكبة أحدث التطورات. من خلال تطبيق هذه الإرشادات، ستتمكن من تسخير قوة Docker لبناء ونشر تطبيقات أكثر كفاءة وموثوقية، مما يجعلك مطورًا أو مهندس DevOps أكثر قيمة في سوق العمل.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين الصورة والحاوية في Docker؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;الصورة (Image) هي قالب ثابت للقراءة فقط يحتوي على التطبيق وجميع تبعياته. أما الحاوية (Container) فهي نسخة قابلة للتشغيل من الصورة، وهي المثيل الحي للتطبيق الذي يمكنك التفاعل معه.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;لماذا يجب استخدام Docker Compose؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;يُستخدم Docker Compose لتعريف وتشغيل تطبيقات Docker متعددة الحاويات بسهولة. يسمح لك بتكوين جميع الخدمات والشبكات والمجلدات اللازمة لتطبيقك في ملف YAML واحد، مما يبسط عملية الإعداد والإدارة لبيئات التطوير المعقدة.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/08/master_0188411957.html'&gt;احتراف Docker: دليلك العملي لأحدث التطورات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>احتراف Google Apps Script: المسار العملي وأحدث التطورات</title><link>https://www.siwane.xyz/2026/08/master.html</link><category>مقالات AI</category><pubDate>Mon, 10 Aug 2026 10:27:53 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-8834905049313872443</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="احتراف Google Apps Script: المسار العملي وأحدث التطورات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف المسار العملي لاحتراف Google Apps Script، من الأساسيات إلى أحدث التطورات، مع نصائح عملية وأمثلة برمجية لتعزيز إنتاجيتك.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم يزداد فيه الاعتماد على الأتمتة والحلول السحابية، يبرز Google Apps Script كأداة قوية لا غنى عنها للمطورين ومحترفي الأعمال على حد سواء. إنها منصة برمجية قائمة على السحابة تتيح لك توسيع وتخصيص وأتمتة تطبيقات Google Workspace (مثل جداول البيانات، المستندات، Gmail، التقويم، و Drive) باستخدام لغة JavaScript. يهدف هذا المقال إلى إرشادك نحو احتراف هذه الأداة وتقديم لمحة عن أحدث التطورات فيها.&lt;/p&gt;

&lt;h2 id="what-is-gas"&gt;ما هو Google Apps Script؟&lt;/h2&gt;
&lt;p&gt;Google Apps Script (GAS) هو بيئة تطوير قائمة على السحابة تمكنك من كتابة أكواد JavaScript للتفاعل مع خدمات Google. لا يتطلب تثبيت أي برامج على جهازك، فكل ما تحتاجه هو متصفح ويب وحساب Google. يتيح لك GAS إنشاء وظائف مخصصة، أتمتة المهام المتكررة، بناء تطبيقات ويب بسيطة، وربط خدمات Google ببعضها البعض أو بخدمات خارجية.&lt;/p&gt;

&lt;h2 id="mastering-gas"&gt;كيفية احتراف Google Apps Script&lt;/h2&gt;
&lt;p&gt;يتطلب احتراف Google Apps Script مزيجًا من المعرفة النظرية والتطبيق العملي. إليك مسار عملي لتحقيق ذلك:&lt;/p&gt;

&lt;h3 id="js-fundamentals"&gt;1. أساسيات JavaScript المتينة&lt;/h3&gt;
&lt;p&gt;بما أن Google Apps Script مبني على JavaScript، فإن الفهم العميق للغة الأم هو حجر الزاوية. ركز على المفاهيم الأساسية مثل:&lt;/p&gt;
&lt;ol class="steps"&gt;
    &lt;li&gt;المتغيرات وأنواع البيانات.&lt;/li&gt;
    &lt;li&gt;الدوال (Functions) وكيفية تعريفها واستدعائها.&lt;/li&gt;
    &lt;li&gt;هياكل التحكم (الشروط والحلقات التكرارية).&lt;/li&gt;
    &lt;li&gt;الكائنات (Objects) والمصفوفات (Arrays).&lt;/li&gt;
    &lt;li&gt;مفاهيم البرمجة غير المتزامنة (Asynchronous Programming) الأساسية، على الرغم من أن GAS يتعامل مع الكثير منها خلف الكواليس.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يستخدم Google Apps Script حاليًا محرك V8 JavaScript، مما يعني أنه يدعم أحدث ميزات اللغة.&lt;/p&gt;

&lt;h3 id="practical-projects"&gt;2. التعلم بالمشاريع العملية&lt;/h3&gt;
&lt;p&gt;لا شيء يضاهي التعلم بالتطبيق. ابدأ بمشاريع صغيرة وبسيطة ثم تدرج إلى الأكثر تعقيدًا:&lt;/p&gt;
&lt;ol class="steps"&gt;
    &lt;li&gt;&lt;b&gt;إنشاء قائمة مخصصة:&lt;/b&gt; أضف قائمة جديدة إلى Google Sheet أو Doc لتشغيل وظيفة معينة.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;أتمتة إرسال البريد الإلكتروني:&lt;/b&gt; اكتب سكربت يرسل رسائل بريد إلكتروني بناءً على بيانات في جدول بيانات.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تسجيل البيانات:&lt;/b&gt; استخدم GAS لتسجيل بيانات من نموذج Google Forms إلى Google Sheet.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تطبيقات الويب البسيطة:&lt;/b&gt; أنشئ تطبيق ويب يعرض بيانات من جدول بيانات أو يتفاعل مع المستخدم.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="explore-google-services"&gt;3. استكشاف خدمات Google المدمجة&lt;/h3&gt;
&lt;p&gt;تكمن قوة GAS في قدرته على التفاعل مع خدمات Google الأخرى. تعرف على الكائنات العالمية (Global Objects) التي توفرها كل خدمة:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;SpreadsheetApp&lt;/code&gt; للتعامل مع جداول البيانات.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;GmailApp&lt;/code&gt; و &lt;code&gt;MailApp&lt;/code&gt; لإرسال واستقبال رسائل البريد الإلكتروني.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;DriveApp&lt;/code&gt; لإدارة الملفات والمجلدات في Google Drive.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;CalendarApp&lt;/code&gt; للتعامل مع التقويمات والأحداث.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;DocumentApp&lt;/code&gt; و &lt;code&gt;FormsApp&lt;/code&gt; للمستندات والنماذج.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;UrlFetchApp&lt;/code&gt; لإجراء طلبات HTTP إلى واجهات برمجة تطبيقات خارجية.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class='pIndent'&gt;اقرأ الوثائق الرسمية لكل خدمة لفهم الطرق (Methods) والخصائص (Properties) المتاحة.&lt;/p&gt;

&lt;h3 id="debugging-optimization"&gt;4. تصحيح الأخطاء والتحسين&lt;/h3&gt;
&lt;p&gt;تعد مهارات تصحيح الأخطاء (Debugging) وتحسين الأداء ضرورية. استخدم:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;Logger.log()&lt;/code&gt; لتتبع قيم المتغيرات وسير عمل السكربت.&lt;/li&gt;
    &lt;li&gt;مصحح الأخطاء المدمج (Debugger) في محرر Apps Script.&lt;/li&gt;
    &lt;li&gt;فهم قيود Apps Script (مثل حدود التنفيذ اليومية) وكيفية تصميم السكربتات لتكون فعالة.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="community-resources"&gt;5. المجتمع والموارد&lt;/h3&gt;
&lt;p&gt;لا تتردد في الاستفادة من المجتمع. تعد وثائق Google Apps Script الرسمية (&lt;a class='extL' href='https://developers.google.com/apps-script/guides/overview' rel='nofollow noreferrer' target='_blank'&gt;Google Developers&lt;/a&gt;) مصدرًا لا يقدر بثمن. كما أن مواقع مثل Stack Overflow ومنتديات Google الخاصة بـ Apps Script توفر حلولًا لمشاكل شائعة.&lt;/p&gt;

&lt;h2 id="latest-developments"&gt;أحدث التطورات في Google Apps Script&lt;/h2&gt;
&lt;p&gt;تشهد Google Apps Script تطورات مستمرة لتعزيز أدائها وقدراتها:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;b&gt;محرك V8 JavaScript:&lt;/b&gt; تم تحديث بيئة التشغيل لدعم محرك V8 JavaScript، مما يوفر أداءً أفضل ويدعم أحدث ميزات JavaScript (مثل &lt;code&gt;async/await&lt;/code&gt;، &lt;code&gt;let&lt;/code&gt;، &lt;code&gt;const&lt;/code&gt;، و &lt;b style='color:var(--linkC)'&gt;arrow functions&lt;/b&gt;).&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Clasp (Command Line Apps Script Project):&lt;/b&gt; أداة سطر أوامر تتيح للمطورين تطوير مشاريع Apps Script محليًا باستخدام محرر الأكواد المفضل لديهم، ثم مزامنتها مع Google Drive. هذا يحسن سير عمل التطوير بشكل كبير.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تحسينات على محرر الأكواد:&lt;/b&gt; تحديثات مستمرة على محرر الأكواد المدمج لتحسين تجربة المستخدم، بما في ذلك إكمال تلقائي أفضل، وتصحيح أخطاء أكثر كفاءة، ودعم أفضل لأنواع TypeScript (على الرغم من أن Apps Script لا يزال يعتمد على JavaScript).&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تكامل أوسع مع Google Cloud Platform:&lt;/b&gt; تسهيل ربط مشاريع Apps Script بخدمات GCP الأخرى، مما يفتح آفاقًا جديدة للمشاريع الأكثر تعقيدًا.&lt;/li&gt;
&lt;/ul&gt;

&lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;عند التعامل مع بيانات حساسة أو واجهات برمجة تطبيقات خارجية، تأكد دائمًا من تطبيق أفضل ممارسات الأمان والتحقق من صحة المدخلات.&lt;/p&gt;

&lt;p&gt;إليك مثال بسيط يوضح كيفية إضافة قائمة مخصصة إلى Google Sheet وتشغيل وظيفة:&lt;/p&gt;
&lt;pre data-comment='JavaScript' data-source='Code.gs'&gt;&lt;code&gt;function onOpen(e) {
  SpreadsheetApp.getUi()
      .createMenu('أدوات مخصصة')
      .addItem('تشغيل وظيفة', 'myCustomFunction')
      .addToUi();
}

function myCustomFunction() {
  SpreadsheetApp.getUi().alert('تم تشغيل الوظيفة المخصصة!');
  Logger.log('تم تنفيذ الوظيفة بنجاح.');
}&lt;/code&gt;&lt;/pre&gt;

&lt;div class='alert info outline'&gt;
    &lt;p&gt;&lt;b&gt;نصيحة!&lt;/b&gt; لتحقيق أقصى استفادة من Google Apps Script، حاول دائمًا كتابة أكواد قابلة لإعادة الاستخدام، واستخدم التعليقات التوضيحية، واختبر وظائفك بانتظام.&lt;/p&gt;
&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل أحتاج إلى معرفة JavaScript لتعلم Google Apps Script؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، معرفة أساسيات JavaScript ضرورية للغاية، حيث أن Google Apps Script مبني عليها بالكامل. كلما كان فهمك لـ JavaScript أعمق، كلما تمكنت من كتابة سكربتات أكثر كفاءة وتعقيدًا.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين Google Apps Script و JavaScript العادي؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;Google Apps Script هو بيئة تشغيل خاصة لـ JavaScript تعمل على خوادم Google. بينما JavaScript العادي يمكن تشغيله في المتصفح (Client-side) أو على الخادم (Node.js)، فإن Apps Script مصمم خصيصًا للتفاعل مع خدمات Google Workspace ويحتوي على كائنات وواجهات برمجة تطبيقات (APIs) فريدة لهذه الخدمات (مثل SpreadsheetApp، GmailApp). كما أنه لا يتطلب إعداد بيئة تطوير محلية.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;p&gt;في الختام، يمثل Google Apps Script أداة قوية ومرنة لأتمتة المهام وتوسيع قدرات Google Workspace. من خلال بناء أساس قوي في JavaScript، والممارسة المستمرة عبر المشاريع العملية، واستكشاف خدمات Google المدمجة، والبقاء على اطلاع بأحدث التطورات، يمكنك احتراف هذه المنصة وتحويل أفكارك إلى حلول عملية تزيد من إنتاجيتك وكفاءتك.&lt;/p&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/08/master.html'&gt;احتراف Google Apps Script: المسار العملي وأحدث التطورات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>احتراف GitHub: دليلك الشامل لأحدث التطورات والممارسات</title><link>https://www.siwane.xyz/2026/07/mastering-github.html</link><category>مقالات AI</category><pubDate>Mon, 27 Jul 2026 10:27:44 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-8681123268067023171</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="احتراف GitHub: دليلك الشامل لأحدث التطورات والممارسات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف كيف تتقن GitHub من الأساسيات إلى الميزات المتقدمة، وتعرف على أحدث الابتكارات مثل Copilot وCodespaces لتعزيز إنتاجيتك.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;تُعد منصة GitHub حجر الزاوية في عالم تطوير البرمجيات الحديث، فهي ليست مجرد خدمة لاستضافة مستودعات Git، بل هي بيئة متكاملة للتعاون، إدارة المشاريع، وأتمتة سير العمل. احتراف GitHub لم يعد خياراً، بل ضرورة لكل مطور يسعى للتميز والإنتاجية.&lt;/p&gt;

&lt;h2 id="what-is-github"&gt;ما هو GitHub ولماذا هو أساسي؟&lt;/h2&gt;
&lt;p&gt;GitHub هي منصة قائمة على الويب تستخدم نظام التحكم في الإصدارات Git. تسمح للمطورين بالتعاون على المشاريع، تتبع التغييرات في الكود، وإدارة دورة حياة تطوير البرمجيات بكفاءة. يكمن جوهر GitHub في تسهيل العمل الجماعي، حيث يمكن لعدة مطورين العمل على نفس المشروع في وقت واحد دون تضارب، مع الحفاظ على سجل كامل ودقيق لجميع التعديلات.&lt;/p&gt;

&lt;h2 id="mastering-github-core-concepts"&gt;احتراف GitHub: المفاهيم الأساسية&lt;/h2&gt;
&lt;p&gt;لتبدأ رحلتك نحو احتراف GitHub، يجب أن تتقن المفاهيم الأساسية لنظام Git وكيفية تطبيقها على GitHub.&lt;/p&gt;

&lt;h3&gt;المستودعات (Repositories)&lt;/h3&gt;
&lt;p&gt;المستودع هو المجلد الرئيسي لمشروعك، حيث يتم تخزين جميع الملفات، الأكواد، وسجل التغييرات. يمكن أن يكون المستودع عاماً (Public) أو خاصاً (Private).&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;إنشاء مستودع جديد:&lt;/b&gt; من واجهة GitHub، اختر "New repository".&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استنساخ مستودع (Cloning):&lt;/b&gt; لجلب نسخة من المستودع إلى جهازك المحلي، استخدم الأمر:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git clone &amp;lt;URL_المستودع&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;التعديلات والالتزامات (Commits)&lt;/h3&gt;
&lt;p&gt;الالتزام هو لقطة للتغييرات التي أجريتها على مشروعك. كل التزام يحتوي على رسالة توضيحية تصف التغييرات.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;إضافة التغييرات للمنطقة المؤقتة (Staging Area):&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/pre&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;إنشاء التزام (Commit):&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git commit -m "رسالة توضيحية للتغييرات"&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;الفروع (Branches)&lt;/h3&gt;
&lt;p&gt;الفروع تسمح لك بالعمل على ميزات جديدة أو إصلاح الأخطاء دون التأثير على الكود الرئيسي للمشروع (عادةً فرع &lt;code&gt;main&lt;/code&gt; أو &lt;code&gt;master&lt;/code&gt;).&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;إنشاء فرع جديد:&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git branch &amp;lt;اسم_الفرع&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;التبديل إلى فرع:&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git checkout &amp;lt;اسم_الفرع&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;دمج الفروع (Merging):&lt;/b&gt; بعد الانتهاء من العمل على فرع، يمكنك دمجه مع الفرع الرئيسي:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git checkout main
git merge &amp;lt;اسم_الفرع&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;الدفع والسحب (Push &amp; Pull)&lt;/h3&gt;
&lt;p&gt;للمزامنة بين المستودع المحلي والمستودع البعيد (على GitHub):&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;الدفع (Push):&lt;/b&gt; لإرسال التغييرات من المستودع المحلي إلى GitHub:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git push origin &amp;lt;اسم_الفرع&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;السحب (Pull):&lt;/b&gt; لجلب التغييرات من GitHub إلى المستودع المحلي:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='Git Command' data-source='terminal'&gt;&lt;code&gt;git pull origin &amp;lt;اسم_الفرع&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="advanced-github-features"&gt;الميزات المتقدمة في GitHub&lt;/h2&gt;
&lt;p&gt;بعد إتقان الأساسيات، يمكنك استكشاف الميزات التي تعزز التعاون وتسرع سير العمل.&lt;/p&gt;

&lt;h3&gt;طلبات السحب (Pull Requests - PRs)&lt;/h3&gt;
&lt;p&gt;هي قلب التعاون في GitHub. تسمح للمطورين باقتراح تغييرات على فرع آخر (عادةً &lt;code&gt;main&lt;/code&gt;). يمكن للمراجعين مناقشة التغييرات، تقديم الملاحظات، والموافقة عليها قبل الدمج.&lt;/p&gt;
&lt;p class='note'&gt;&lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;اكتب رسائل PR واضحة وموجزة، واشرح الغرض من التغييرات، وكيف تم اختبارها.&lt;/p&gt;

&lt;h3&gt;المشكلات (Issues)&lt;/h3&gt;
&lt;p&gt;أداة لتتبع الأخطاء، طلبات الميزات، وتحسينات المشروع. يمكن ربط المشكلات بطلبات السحب لتتبع التقدم.&lt;/p&gt;

&lt;h3&gt;إجراءات GitHub (GitHub Actions)&lt;/h3&gt;
&lt;p&gt;تتيح لك أتمتة مهام سير العمل مباشرة داخل مستودعك. يمكنك بناء، اختبار، ونشر الكود تلقائياً عند كل دفع أو طلب سحب. هذا يمثل أساس &lt;b style='color:var(--linkC)'&gt;الدمج المستمر (CI) والنشر المستمر (CD)&lt;/b&gt;.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
  &lt;b&gt;مثال:&lt;/b&gt; يمكنك إعداد GitHub Action لتشغيل اختبارات الوحدة تلقائياً في كل مرة يتم فيها دفع كود جديد إلى فرع &lt;code&gt;main&lt;/code&gt;.
&lt;/div&gt;

&lt;h3&gt;صفحات GitHub (GitHub Pages)&lt;/h3&gt;
&lt;p&gt;خدمة استضافة مجانية للمواقع الثابتة مباشرة من مستودعك. مثالية للمدونات، وثائق المشاريع، أو السير الذاتية.&lt;/p&gt;

&lt;h2 id="latest-github-developments"&gt;أحدث التطورات في GitHub&lt;/h2&gt;
&lt;p class='pIndent'&gt;تتطور GitHub باستمرار لتقديم أدوات أكثر قوة وذكاءً للمطورين.&lt;/p&gt;

&lt;h3&gt;GitHub Copilot&lt;/h3&gt;
&lt;p&gt;مساعد برمجة يعمل بالذكاء الاصطناعي، تم تطويره بالتعاون مع OpenAI. يقترح Copilot سطوراً كاملة من الكود أو دوال بناءً على السياق الذي تكتب فيه، مما يزيد من سرعة البرمجة ويقلل من الأخطاء.&lt;/p&gt;

&lt;h3&gt;GitHub Codespaces&lt;/h3&gt;
&lt;p&gt;بيئات تطوير فورية وقابلة للتكوين بالكامل تعمل في السحابة. تتيح لك بدء العمل على مشروعك في ثوانٍ من أي جهاز، دون الحاجة لإعداد بيئة تطوير محلية معقدة. هذا يعزز المرونة ويقلل من وقت الإعداد.&lt;/p&gt;

&lt;h3&gt;تحسينات الأمان (Security Enhancements)&lt;/h3&gt;
&lt;p&gt;تواصل GitHub تعزيز ميزات الأمان مثل &lt;b style='color:var(--linkC)'&gt;Dependabot&lt;/b&gt; الذي يقوم بفحص تبعيات مشروعك للكشف عن الثغرات الأمنية وتحديثها تلقائياً، و &lt;b style='color:var(--linkC)'&gt;Code Scanning&lt;/b&gt; الذي يكتشف الثغرات الأمنية في الكود الخاص بك قبل النشر.&lt;/p&gt;

&lt;h3&gt;الدمج مع الذكاء الاصطناعي (AI Integration)&lt;/h3&gt;
&lt;p&gt;بالإضافة إلى Copilot، تستكشف GitHub المزيد من طرق دمج الذكاء الاصطناعي لتحسين تجربة المطور، مثل تلخيص طلبات السحب، اقتراح مراجعات الكود، وتحسين البحث عن الكود.&lt;/p&gt;

&lt;h2 id="best-practices-for-mastery"&gt;أفضل الممارسات لاحتراف GitHub&lt;/h2&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;رسائل الالتزام الواضحة:&lt;/b&gt; اكتب رسائل التزام وصفية وموجزة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استراتيجيات الفروع:&lt;/b&gt; استخدم استراتيجيات مثل &lt;b style='color:var(--linkC)'&gt;Git Flow&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;GitHub Flow&lt;/b&gt; لإدارة الفروع بفعالية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;مراجعة الكود:&lt;/b&gt; شارك في مراجعة الكود لتعلم من الآخرين وتحسين جودة الكود.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استخدام القوالب:&lt;/b&gt; استخدم قوالب لطلبات السحب والمشكلات لتوحيد المعلومات المطلوبة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التعلم المستمر:&lt;/b&gt; تابع مدونة GitHub الرسمية وقنوات المطورين للبقاء على اطلاع بأحدث الميزات والتطورات.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين Git و GitHub؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;Git هو نظام تحكم في الإصدارات موزع (DVCS) لتتبع التغييرات في الكود. GitHub هي منصة قائمة على الويب تستضيف مستودعات Git وتوفر أدوات للتعاون وإدارة المشاريع.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل GitHub مجاني للاستخدام؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، GitHub يقدم خطة مجانية للمستودعات العامة والخاصة، مع قيود على بعض الميزات المتقدمة التي تتطلب خططاً مدفوعة.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هي أهمية GitHub Actions؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;تسمح GitHub Actions بأتمتة مهام سير العمل مثل بناء الكود، اختباره، ونشره، مما يسرع عملية التطوير ويضمن جودة الكود من خلال الدمج المستمر والنشر المستمر (CI/CD).&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/07/mastering-github.html'&gt;احتراف GitHub: دليلك الشامل لأحدث التطورات والممارسات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>تحديد نطاق خصائص CSS المخصصة: بديل فعال لمتغيرات الثيم الجذرية؟</title><link>https://www.siwane.xyz/2026/07/component.html</link><category>مقالات AI</category><pubDate>Mon, 20 Jul 2026 10:27:53 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-2390919712441672036</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="تحديد نطاق خصائص CSS المخصصة: بديل فعال لمتغيرات الثيم الجذرية؟" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;هل تحديد نطاق خصائص CSS المخصصة على جذر المكون يوفر بديلاً جيدًا لمتغيرات الثيم العالمية في :root؟ تحليل تقني لفوائد وعيوب كل نهج.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الويب الحديث، أصبحت إدارة الأنماط القابلة للتخصيص والصيانة أمرًا بالغ الأهمية. توفر خصائص CSS المخصصة (المعروفة أيضًا بمتغيرات CSS) أداة قوية لتحقيق ذلك، ولكن السؤال يظل: أين يجب تعريف هذه المتغيرات؟ هل يجب أن تكون عالمية على مستوى &lt;code&gt;:root&lt;/code&gt;، أم يجب تحديد نطاقها على مستوى المكونات الفردية؟ يستكشف هذا المقال هذا التساؤل، مقدمًا تحليلاً عمليًا لمساعدتك في اتخاذ القرار الأنسب لمشاريعك.&lt;/p&gt;

&lt;h2 id="understanding-css-custom-properties"&gt;فهم خصائص CSS المخصصة&lt;/h2&gt;
&lt;p&gt;خصائص CSS المخصصة هي كيانات معرفة من قبل المؤلف تحتوي على قيم يمكن إعادة استخدامها في مستند CSS. يتم تعريفها باستخدام بادئة مزدوجة الشرطة (&lt;code&gt;--&lt;/code&gt;) ويمكن الوصول إليها باستخدام دالة &lt;code&gt;var()&lt;/code&gt;. تتيح هذه الخصائص إنشاء أنظمة تصميم ديناميكية ومرنة، مما يسهل إدارة الثيمات والتخصيصات.&lt;/p&gt;

&lt;pre data-comment='CSS' data-source='variables.css'&gt;&lt;code&gt;
:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
}

.button {
  background-color: var(--primary-color);
  color: white;
  padding: 10px 15px;
  border: none;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="global-root-variables"&gt;متغيرات الثيم العالمية في :root&lt;/h2&gt;
&lt;p&gt;تقليديًا، يتم تعريف متغيرات الثيم الأساسية (مثل الألوان الرئيسية، أحجام الخطوط، المسافات) على مستوى &lt;code&gt;:root&lt;/code&gt;. هذا النهج يوفر نقطة مركزية واحدة لإدارة الثيم بالكامل، مما يجعله سهل التحديث والتغيير على نطاق واسع.&lt;/p&gt;

&lt;h3 id="advantages-of-global-variables"&gt;مزايا المتغيرات العالمية&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;سهولة الإدارة المركزية:&lt;/b&gt; يمكن تغيير قيمة واحدة في &lt;code&gt;:root&lt;/code&gt; لتنعكس على الفور في كل مكان يتم استخدام هذا المتغير فيه.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الاتساق الشامل:&lt;/b&gt; يضمن تطبيق ثيم متسق عبر التطبيق بأكمله.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الوصول السهل:&lt;/b&gt; يمكن الوصول إلى أي متغير معرف في &lt;code&gt;:root&lt;/code&gt; من أي مكان في شجرة DOM بسبب آلية التتالي.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="disadvantages-of-global-variables"&gt;عيوب المتغيرات العالمية&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;احتمال التضارب:&lt;/b&gt; قد يؤدي تعريف عدد كبير من المتغيرات العالمية إلى تضارب في الأسماء أو صعوبة في تتبع استخداماتها.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;نقص التغليف:&lt;/b&gt; لا توفر المتغيرات العالمية أي تغليف، مما يعني أن أي مكون يمكنه الوصول إليها وتعديلها، مما قد يؤدي إلى آثار جانبية غير مقصودة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;صعوبة التخصيص المحلي:&lt;/b&gt; إذا كان مكون معين يحتاج إلى تجاوز قيمة عالمية، فقد يتطلب ذلك كتابة CSS إضافي أو استخدام متغيرات جديدة، مما يزيد من التعقيد.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="scoping-on-component-root"&gt;تحديد النطاق على جذر المكون&lt;/h2&gt;
&lt;p&gt;يقوم هذا النهج بتعريف خصائص CSS المخصصة مباشرة على العنصر الجذر للمكون (مثل &lt;code&gt;.my-component&lt;/code&gt;). هذا يعني أن المتغيرات تكون متاحة فقط داخل هذا المكون وذريته، مما يوفر مستوى من التغليف.&lt;/p&gt;

&lt;pre data-comment='CSS' data-source='component.css'&gt;&lt;code&gt;
.card {
  --card-bg-color: #ffffff;
  --card-border-radius: 8px;
  background-color: var(--card-bg-color);
  border-radius: var(--card-border-radius);
  padding: 20px;
  border: 1px solid #eee;
}

.card.dark {
  --card-bg-color: #333333; /* Override for dark theme */
  color: white;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="advantages-of-component-scoping"&gt;مزايا تحديد النطاق على المكون&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;التغليف المعزز:&lt;/b&gt; تظل المتغيرات محصورة داخل المكون، مما يقلل من خطر التضارب مع الأنماط الأخرى في التطبيق.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;النمطية وقابلية إعادة الاستخدام:&lt;/b&gt; يصبح المكون أكثر استقلالية وقابلية لإعادة الاستخدام، حيث يحمل معه جميع متغيراته الخاصة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;سهولة التخصيص المحلي:&lt;/b&gt; يمكن للمكونات بسهولة تجاوز قيم المتغيرات الخاصة بها دون التأثير على المكونات الأخرى أو الثيم العام.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;وضوح الكود:&lt;/b&gt; يصبح من الواضح أي المتغيرات تنتمي إلى أي مكون، مما يسهل الصيانة والفهم.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="disadvantages-of-component-scoping"&gt;عيوب تحديد النطاق على المكون&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;صعوبة تطبيق الثيم الشامل:&lt;/b&gt; إذا كان كل مكون يحدد متغيراته الخاصة، فقد يصبح من الصعب فرض ثيم موحد على مستوى التطبيق بأكمله.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;التكرار المحتمل:&lt;/b&gt; قد تضطر إلى تعريف متغيرات متشابهة (مثل &lt;code&gt;--text-color&lt;/code&gt;) في مكونات متعددة، مما يؤدي إلى تكرار الكود.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تعقيد إدارة الثيمات المعقدة:&lt;/b&gt; في أنظمة التصميم الكبيرة ذات الثيمات المتعددة، قد يصبح تتبع المتغيرات المحلية وتنسيقها أمرًا معقدًا.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="hybrid-approach-best-of-both-worlds"&gt;النهج الهجين: الأفضل من العالمين&lt;/h2&gt;
&lt;p class='pIndent'&gt;في كثير من الحالات، يكون النهج الأمثل هو الجمع بين كلا الطريقتين. يمكن استخدام متغيرات &lt;code&gt;:root&lt;/code&gt; لتعريف القيم الأساسية للثيم العام (مثل لوحة الألوان الأساسية، الخطوط، المسافات القياسية). بعد ذلك، يمكن للمكونات استخدام هذه المتغيرات العالمية كقيم افتراضية، مع القدرة على تعريف متغيرات خاصة بها أو تجاوز القيم العالمية عند الحاجة.&lt;/p&gt;

&lt;pre data-comment='CSS' data-source='hybrid-approach.css'&gt;&lt;code&gt;
:root {
  --global-primary-color: #007bff;
  --global-font-size: 16px;
}

.button {
  --button-bg-color: var(--global-primary-color); /* Use global as default */
  --button-font-size: var(--global-font-size);
  background-color: var(--button-bg-color);
  font-size: var(--button-font-size);
  padding: 10px 15px;
}

.button.alt {
  --button-bg-color: #28a745; /* Override locally */
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يسمح هذا النهج الهجين بالاستفادة من الاتساق الذي توفره المتغيرات العالمية، مع الحفاظ على مرونة وتغليف المكونات الفردية.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;الخلاصة&lt;/h2&gt;
&lt;p&gt;تحديد نطاق خصائص CSS المخصصة على جذر المكون هو بالتأكيد بديل جيد لمتغيرات الثيم العالمية، خاصة عندما يكون الهدف هو تعزيز التغليف، النمطية، وقابلية إعادة استخدام المكونات. ومع ذلك، فإنه ليس حلاً شاملاً لكل السيناريوهات. للحصول على أفضل النتائج، يوصى بتبني &lt;b style='color:var(--linkC)'&gt;نهج هجين&lt;/b&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;استخدم &lt;code&gt;:root&lt;/code&gt; لتعريف المتغيرات الأساسية التي تشكل جوهر نظام التصميم الخاص بك وتتطلب اتساقًا شاملاً.&lt;/li&gt;
  &lt;li&gt;استخدم تحديد النطاق على مستوى المكون لتعريف المتغيرات الخاصة بالمكون، أو لتوفير تجاوزات محلية للقيم العالمية.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;هذا التوازن يضمن أن تتمتع بتوحيد الثيم على مستوى التطبيق، مع الحفاظ على مرونة المكونات واستقلاليتها، مما يؤدي إلى قاعدة كود CSS أكثر قابلية للصيانة والتوسع.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق الرئيسي بين متغيرات :root والمتغيرات المحددة النطاق على المكون؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;متغيرات &lt;code&gt;:root&lt;/code&gt; هي عالمية ومتاحة في أي مكان في شجرة DOM، مما يجعلها مثالية للثيمات الشاملة. أما المتغيرات المحددة النطاق على المكون، فهي متاحة فقط داخل المكون نفسه وذريته، مما يوفر تغليفًا أفضل وقابلية لإعادة الاستخدام.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكنني استخدام متغير عالمي كقيمة افتراضية لمتغير محلي؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، هذا هو جوهر النهج الهجين. يمكنك تعريف متغير عالمي في &lt;code&gt;:root&lt;/code&gt;، ثم استخدام هذا المتغير كقيمة لمتغير محلي داخل مكون، مع إمكانية تجاوز القيمة المحلية لاحقًا إذا لزم الأمر.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/07/component.html'&gt;تحديد نطاق خصائص CSS المخصصة: بديل فعال لمتغيرات الثيم الجذرية؟&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>حل مشكلة TS7053: الوصول الآمن للقيم المفهرسة في TypeScript و Angular</title><link>https://www.siwane.xyz/2026/07/typescript-ts.html</link><category>مقالات AI</category><pubDate>Mon, 13 Jul 2026 10:27:49 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-7643535015135853190</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="حل مشكلة TS7053: الوصول الآمن للقيم المفهرسة في TypeScript و Angular" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;استكشف الحلول العملية لمشكلة TS7053 عند محاولة الوصول إلى القيم المفهرسة ديناميكياً من كائن environment في Angular، مع التركيز على السلامة والتصنيف القوي.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;تُعد مشكلة TS7053، التي تشير إلى "Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'", من الأخطاء الشائعة التي يواجهها المطورون عند محاولة الوصول إلى خصائص كائن ديناميكياً في TypeScript دون توفير معلومات كافية عن النوع. يبرز هذا الخطأ بشكل خاص في سياق Angular عند محاولة تهيئة خاصية لمكون باستخدام قيمة مفهرسة مأخوذة من كائن `environment`.&lt;/p&gt;

&lt;h2 id="understanding-ts7053"&gt;فهم خطأ TS7053&lt;/h2&gt;
&lt;p&gt;يحدث خطأ TS7053 عندما يحاول TypeScript الوصول إلى خاصية كائن باستخدام مفتاح ديناميكي (مثل متغير سلسلة) ولا يستطيع المترجم التأكد من أن الكائن يمتلك هذه الخاصية أو أن نوعها معروف. في السيناريو المحدد الذي ذكرته:&lt;/p&gt;
&lt;pre data-comment='HTML' data-source='app.component.html'&gt;&lt;code&gt;&amp;lt;app-carte [id] = &amp;quot;environment[region + '_id']&amp;quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;يفترض TypeScript أن الكائن `environment` قد لا يحتوي على مفتاح مثل &lt;code&gt;'dev_id'&lt;/code&gt; أو &lt;code&gt;'prod_id'&lt;/code&gt;، أو أنه لا يمتلك توقيع فهرس (index signature) يسمح بالوصول إليه باستخدام سلسلة. هذا السلوك هو جزء من نظام الأنواع الصارم في TypeScript لضمان السلامة ومنع أخطاء وقت التشغيل.&lt;/p&gt;

&lt;h2 id="practical-solutions"&gt;حلول عملية&lt;/h2&gt;
&lt;p&gt;لحل هذه المشكلة، نحتاج إلى تزويد TypeScript بمعلومات نوعية كافية حول كائن `environment` ليعرف أنه يمكن الوصول إليه ديناميكياً. إليك عدة طرق للقيام بذلك، بدءاً من الأقل أماناً وصولاً إلى الأكثر قوة.&lt;/p&gt;

&lt;h3 id="solution-1-type-assertion"&gt;الحل 1: تأكيد النوع (Type Assertion)&lt;/h3&gt;
&lt;p&gt;تأكيد النوع هو أسرع طريقة لتجاوز الخطأ، لكنه يقلل من سلامة النوع. أنت تخبر TypeScript بشكل أساسي "أنا أعرف أفضل، ثق بي".&lt;/p&gt;
&lt;pre data-comment='TypeScript' data-source='app.component.ts'&gt;&lt;code&gt;import { Component } from '@angular/core';
import { environment } from 'src/environments/environment'; // تأكد من المسار الصحيح

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  region: string = 'dev'; // أو أي قيمة أخرى
  env = environment; // اجعل environment متاحاً في القالب

  // في القالب: &amp;lt;app-carte [id]="getCarteId()"&amp;gt;
  getCarteId(): string {
    const key = this.region + '_id';
    // تأكيد النوع هنا: نخبر TypeScript أن env هو Record&lt;string, any&gt;
    return (this.env as Record&amp;lt;string, any&amp;gt;)[key];
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;استخدام &lt;code&gt;any&lt;/code&gt; أو &lt;code&gt;Record&amp;lt;string, any&amp;gt;&lt;/code&gt; يزيل فحص النوع لهذه الخاصية، مما قد يؤدي إلى أخطاء وقت التشغيل إذا لم تكن الخاصية موجودة بالفعل.&lt;/p&gt;

&lt;h3 id="solution-2-type-guard"&gt;الحل 2: حارس النوع (Type Guard)&lt;/h3&gt;
&lt;p&gt;يمكنك استخدام حارس النوع للتحقق من وجود الخاصية قبل محاولة الوصول إليها. هذا يضيف طبقة من الأمان ولكنه لا يحل مشكلة TS7053 مباشرة في القالب ما لم يتم دمجها مع تأكيد النوع أو إعادة هيكلة الكود.&lt;/p&gt;
&lt;pre data-comment='TypeScript' data-source='app.component.ts'&gt;&lt;code&gt;import { Component } from '@angular/core';
import { environment } from 'src/environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  region: string = 'dev';
  env = environment;

  getCarteId(): string | undefined {
    const key = this.region + '_id';
    // استخدام حارس النوع للتحقق من وجود الخاصية
    if (key in this.env) {
      // لا يزال قد يتطلب تأكيد نوع إذا كان env غير مصنف بشكل جيد
      return (this.env as Record&amp;lt;string, string&amp;gt;)[key];
    }
    return undefined; // أو قيمة افتراضية
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;في القالب، ستحتاج إلى التعامل مع القيمة المحتملة &lt;code&gt;undefined&lt;/code&gt;:&lt;/p&gt;
&lt;pre data-comment='HTML' data-source='app.component.html'&gt;&lt;code&gt;&amp;lt;app-carte [id]="getCarteId() || 'default_id'"&amp;gt;&amp;lt;/app-carte&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="solution-3-strong-typing-with-index-signature"&gt;الحل 3: التصنيف القوي مع توقيع الفهرس (Index Signature) - الحل الموصى به&lt;/h3&gt;
&lt;p&gt;هذا هو الحل الأكثر قوة وسلامة. قم بتعريف واجهة (interface) لكائن `environment` تتضمن توقيع فهرس. هذا يخبر TypeScript صراحة أن الكائن يمكن الوصول إليه باستخدام مفاتيح سلسلة.&lt;/p&gt;

&lt;ol class="steps"&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;تعريف الواجهة:&lt;/b&gt; أنشئ واجهة في ملف منفصل (مثل &lt;code&gt;src/app/types/environment.ts&lt;/code&gt;) أو مباشرة في ملف `environment.ts` الخاص بك.&lt;/p&gt;
    &lt;pre data-comment='TypeScript' data-source='src/app/types/environment.ts'&gt;&lt;code&gt;export interface AppEnvironment {
  production: boolean;
  apiUrl: string;
  // توقيع الفهرس: يسمح بالوصول إلى أي خاصية بسلسلة
  // ويحدد أن قيم هذه الخصائص ستكون من نوع string (أو أي نوع آخر مناسب)
  [key: string]: string | boolean;
}
&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;إذا كانت بعض خصائص &lt;code&gt;environment&lt;/code&gt; ليست من نوع &lt;code&gt;string&lt;/code&gt; (مثل &lt;code&gt;production: boolean&lt;/code&gt;)، فيجب أن يشمل توقيع الفهرس جميع الأنواع المحتملة (مثال: &lt;code&gt;string | boolean&lt;/code&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;تطبيق الواجهة على كائن &lt;code&gt;environment&lt;/code&gt;:&lt;/b&gt; قم بتحديث ملفات &lt;code&gt;environment.ts&lt;/code&gt; و &lt;code&gt;environment.prod.ts&lt;/code&gt; لتتوافق مع الواجهة.&lt;/p&gt;
    &lt;pre data-comment='TypeScript' data-source='src/environments/environment.ts'&gt;&lt;code&gt;import { AppEnvironment } from '../app/types/environment'; // تأكد من المسار

export const environment: AppEnvironment = {
  production: false,
  apiUrl: 'http://localhost:3000',
  dev_id: 'dev_carte_123',
  test_id: 'test_carte_456'
};
&lt;/code&gt;&lt;/pre&gt;
    &lt;pre data-comment='TypeScript' data-source='src/environments/environment.prod.ts'&gt;&lt;code&gt;import { AppEnvironment } from '../app/types/environment'; // تأكد من المسار

export const environment: AppEnvironment = {
  production: true,
  apiUrl: 'https://api.yourdomain.com',
  prod_id: 'prod_carte_789'
};
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;استخدام الكائن المصنف في المكون:&lt;/b&gt; الآن، يمكن لـ TypeScript فهم الوصول الديناميكي بأمان.&lt;/p&gt;
    &lt;pre data-comment='TypeScript' data-source='app.component.ts'&gt;&lt;code&gt;import { Component } from '@angular/core';
import { environment } from 'src/environments/environment'; // سيعرف TypeScript الآن نوعه

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  region: string = 'dev';
  env = environment; // env الآن من نوع AppEnvironment

  // لا حاجة لدالة مساعدة إذا كان الوصول مباشراً في القالب
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;b&gt;تحديث القالب:&lt;/b&gt;&lt;/p&gt;
    &lt;pre data-comment='HTML' data-source='app.component.html'&gt;&lt;code&gt;&amp;lt;!-- TypeScript الآن سعيد لأن env لديه توقيع فهرس --&amp;gt;
&amp;lt;app-carte [id]="env[region + '_id'] as string"&amp;gt;&amp;lt;/app-carte&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
    &lt;p&gt;لاحظ أن &lt;code&gt;as string&lt;/code&gt; قد يكون ضرورياً إذا كان توقيع الفهرس يسمح بأنواع متعددة (مثل &lt;code&gt;string | boolean&lt;/code&gt;) وكنت تحتاج إلى &lt;code&gt;string&lt;/code&gt; بشكل خاص.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="conclusion-and-best-practices"&gt;الخاتمة وأفضل الممارسات&lt;/h2&gt;
&lt;p&gt;يُعد التصنيف القوي لكائن &lt;code&gt;environment&lt;/code&gt; باستخدام توقيع الفهرس هو الحل الأكثر أماناً واستدامة لمشكلة TS7053. إنه يضمن أن الكود الخاص بك متوافق مع مبادئ TypeScript للسلامة النوعية، ويقلل من الأخطاء المحتملة في وقت التشغيل، ويوفر تجربة تطوير أفضل مع إكمال الكود والتحقق من الأخطاء.&lt;/p&gt;
&lt;p class='pIndent'&gt;تجنب استخدام &lt;code&gt;any&lt;/code&gt; قدر الإمكان، واعتمد على التصنيف الصريح لتعزيز موثوقية وقابلية صيانة تطبيقك.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هو توقيع الفهرس (Index Signature) في TypeScript؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;توقيع الفهرس هو ميزة في TypeScript تسمح لك بتعريف أنواع الخصائص التي يمكن الوصول إليها ديناميكياً في كائن باستخدام مفتاح (عادةً سلسلة أو رقم). يتم تعريفه بالشكل &lt;code&gt;[key: string]: Type&lt;/code&gt; أو &lt;code&gt;[index: number]: Type&lt;/code&gt; داخل واجهة أو نوع.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكنني استخدام Optional Chaining مع الوصول المفهرس؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكنك استخدام Optional Chaining (&lt;code&gt;?.&lt;/code&gt;) إذا كان الكائن نفسه قد يكون &lt;code&gt;null&lt;/code&gt; أو &lt;code&gt;undefined&lt;/code&gt;، ولكن ليس للوصول المفهرس مباشرة. ومع ذلك، يمكنك دمجه مع Nullish Coalescing (&lt;code&gt;??&lt;/code&gt;) لتوفير قيمة افتراضية إذا كانت الخاصية غير موجودة أو &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt; بعد الوصول الآمن للنوع. مثال: &lt;code&gt;env[key] ?? 'default_value'&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين &lt;code&gt;as any&lt;/code&gt; و &lt;code&gt;as Record&amp;lt;string, any&amp;gt;&lt;/code&gt;؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;&lt;code&gt;as any&lt;/code&gt; يزيل كل فحص للنوع من هذا التعبير، مما يجعله غير آمن تماماً. &lt;code&gt;as Record&amp;lt;string, any&amp;gt;&lt;/code&gt; يخبر TypeScript أن الكائن هو كائن عام حيث يمكن أن يكون لأي مفتاح سلسلة قيمة من نوع &lt;code&gt;any&lt;/code&gt;. إنه أكثر تحديداً قليلاً من &lt;code&gt;any&lt;/code&gt; ولكنه لا يزال يقلل من السلامة النوعية بشكل كبير للوصول الديناميكي.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/07/typescript-ts.html'&gt;حل مشكلة TS7053: الوصول الآمن للقيم المفهرسة في TypeScript و Angular&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>TypeScript: تحديات متقدمة في قيود الأنواع، حل الوحدات، واستنتاج العموميات</title><link>https://www.siwane.xyz/2026/07/advanced-typescript-type-constraints.html</link><category>مقالات AI</category><pubDate>Fri, 10 Jul 2026 20:08:16 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-4907466292702782690</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="TypeScript: تحديات متقدمة في قيود الأنواع، حل الوحدات، واستنتاج العموميات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;استكشف تحديات TypeScript المتقدمة في قيود الأنواع الصارمة، حل وحدات Angular، ومشكلات استنتاج العموميات غير المشروط.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير البرمجيات الحديث، أصبحت TypeScript أداة لا غنى عنها لبناء تطبيقات قوية وقابلة للصيانة. بفضل نظام الأنواع القوي الذي توفره، يمكن للمطورين اكتشاف الأخطاء مبكرًا وتحسين جودة الكود. ومع ذلك، فإن الغوص في أعماق TypeScript يكشف عن تحديات متقدمة تتطلب فهمًا دقيقًا للمفاهيم الأساسية والمتقدمة. يستكشف هذا المقال ثلاثة من هذه التحديات: تطبيق قيود القراءة فقط الصارمة، معالجة أخطاء حل الوحدات في Angular، ومشكلة تقاطع الأنواع غير المشروط من استنتاج الأنواع العامة.&lt;/p&gt;

&lt;h2 id="strict-readonly-constraints"&gt;تطبيق قيود القراءة فقط الصارمة (Strict Readonly Constraints)&lt;/h2&gt;
&lt;p&gt;يُعد ضمان ثبات البيانات (Immutability) مبدأ تصميميًا أساسيًا في العديد من أنماط البرمجة، خاصة في التطبيقات التي تعتمد على إدارة الحالة المعقدة. توفر TypeScript أدوات قوية لفرض قيود القراءة فقط على مستوى الأنواع، مما يمنع التعديلات غير المقصودة على الخصائص أو الكائنات.&lt;/p&gt;
&lt;h3&gt;استخدام معدل &lt;code&gt;readonly&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;المعدل &lt;code&gt;readonly&lt;/code&gt; هو الطريقة الأكثر وضوحًا لتعيين خاصية كقراءة فقط. يمكن تعيين قيمتها فقط أثناء التهيئة أو داخل مُنشئ الكلاس.&lt;/p&gt;
&lt;pre data-comment='TypeScript' data-source='user.ts'&gt;&lt;code&gt;interface User {
  readonly id: string;
  name: string;
}

const user: User = { id: "123", name: "أحمد" };
user.name = "علي"; // مسموح
// user.id = "456"; // خطأ: لا يمكن تعيين 'id' لأنه خاصية للقراءة فقط.&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;الأنواع المساعدة &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;لفرض قيود القراءة فقط على جميع خصائص كائن موجود، يمكن استخدام النوع المساعد &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;. هذا النوع ينشئ نوعًا جديدًا تكون جميع خصائصه للقراءة فقط.&lt;/p&gt;
&lt;pre data-comment='TypeScript' data-source='config.ts'&gt;&lt;code&gt;interface Config {
  apiUrl: string;
  timeout: number;
}

const defaultConfig: Readonly&amp;lt;Config&amp;gt; = {
  apiUrl: "https://api.example.com",
  timeout: 5000,
};

// defaultConfig.apiUrl = "https://new.api.com"; // خطأ: لا يمكن تعيين 'apiUrl' لأنه خاصية للقراءة فقط.&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;ضمان الثبات العميق (Deep Immutability)&lt;/h3&gt;
&lt;p&gt;تحدي &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt; هو أنه يطبق القيد على المستوى السطحي فقط. إذا كانت الخاصية نفسها كائنًا، فستظل قابلة للتعديل. لفرض ثبات عميق، نحتاج إلى أنواع مساعدة مخصصة أو مكتبات.&lt;/p&gt;
&lt;pre data-comment='TypeScript' data-source='deepReadonly.ts'&gt;&lt;code&gt;type DeepReadonly&amp;lt;T&amp;gt; = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly&amp;lt;T[P]&amp;gt; : T[P];
};

interface Settings {
  user: {
    id: string;
    preferences: { theme: string };
  };
}

const appSettings: DeepReadonly&amp;lt;Settings&amp;gt; = {
  user: {
    id: "user1",
    preferences: { theme: "dark" },
  },
};

// appSettings.user.preferences.theme = "light"; // خطأ: لا يمكن تعيين 'theme' لأنه خاصية للقراءة فقط.&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يُعد الثبات العميق أمرًا بالغ الأهمية في أنماط مثل Redux أو React Context لضمان عدم حدوث طفرات غير متوقعة في الحالة.&lt;/p&gt;

&lt;h2 id="angular-import-error-991010"&gt;معالجة خطأ استيراد مكونات Angular (-991010) مع مسارات TypeScript&lt;/h2&gt;
&lt;p&gt;يواجه العديد من مطوري Angular خطأ &lt;code&gt;-991010&lt;/code&gt; عند استخدام تعيينات &lt;code&gt;paths&lt;/code&gt; في ملف &lt;code&gt;tsconfig.json&lt;/code&gt; لتنظيم الاستيرادات. يشير هذا الخطأ عادةً إلى مشكلة في حل الوحدات (Module Resolution)، حيث لا يتمكن TypeScript أو أدوات البناء من تحديد موقع الوحدات المستوردة بشكل صحيح.&lt;/p&gt;
&lt;h3&gt;الأسباب الجذرية&lt;/h3&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;تكوين &lt;code&gt;tsconfig.json&lt;/code&gt; غير صحيح:&lt;/b&gt; قد لا تكون &lt;code&gt;baseUrl&lt;/code&gt; أو &lt;code&gt;paths&lt;/code&gt; محددة بشكل صحيح، أو قد لا تتطابق مع بنية المشروع الفعلية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;عدم فهم أدوات البناء للمسارات:&lt;/b&gt; لا تفهم أدوات البناء مثل Webpack أو Rollup تعيينات &lt;code&gt;paths&lt;/code&gt; في &lt;code&gt;tsconfig.json&lt;/code&gt; بشكل افتراضي.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;مشاكل في بيئة وقت التشغيل (Node.js):&lt;/b&gt; عند تشغيل الاختبارات أو الخوادم في Node.js، قد لا يتم حل المسارات المستعارة بشكل صحيح.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;استراتيجيات تصحيح الأخطاء والحلول&lt;/h3&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;التحقق من &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;/b&gt;
    &lt;p&gt;تأكد من أن &lt;code&gt;baseUrl&lt;/code&gt; يشير إلى الجذر المشترك لجميع الوحدات، وأن &lt;code&gt;paths&lt;/code&gt; تعكس المسارات الصحيحة.&lt;/p&gt;
    &lt;pre data-comment='JSON' data-source='tsconfig.json'&gt;&lt;code&gt;{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@app/*": ["app/*"],
      "@env/*": ["environments/*"],
      "@shared/*": ["app/shared/*"]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تكوين أدوات البناء (Angular CLI):&lt;/b&gt;
    &lt;p&gt;عادةً ما يتعامل Angular CLI مع هذا الأمر تلقائيًا. إذا كنت تستخدم تكوينًا مخصصًا لـ Webpack، فتأكد من إضافة &lt;code&gt;TsConfigPathsPlugin&lt;/code&gt; أو تكوين &lt;code&gt;alias&lt;/code&gt; يدويًا.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;حل المسارات في Node.js:&lt;/b&gt;
    &lt;p&gt;لبيئات Node.js (مثل الاختبارات باستخدام Jest)، استخدم حزمًا مثل &lt;code&gt;tsconfig-paths&lt;/code&gt; أو &lt;code&gt;module-alias&lt;/code&gt; لتمكين Node.js من فهم تعيينات &lt;code&gt;paths&lt;/code&gt;.&lt;/p&gt;
    &lt;pre data-comment='TypeScript' data-source='setup-jest.ts'&gt;&lt;code&gt;// في ملف إعداد Jest (مثل setup-jest.ts)
import 'tsconfig-paths/register';&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تجنب المسارات المطلقة في بعض الحالات:&lt;/b&gt;
    &lt;p&gt;في بعض الأحيان، قد يكون استخدام الاستيرادات النسبية (&lt;code&gt;../../&lt;/code&gt;) أكثر موثوقية للمكونات الداخلية جدًا، خاصة إذا كانت تعيينات المسارات معقدة.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;يمكن أن يؤدي التكوين الخاطئ لـ &lt;code&gt;baseUrl&lt;/code&gt; و &lt;code&gt;paths&lt;/code&gt; إلى مشاكل في الأداء أثناء عملية البناء أو أخطاء في وقت التشغيل.&lt;/p&gt;

&lt;h2 id="unconditional-type-intersection"&gt;مشكلة تقاطع الأنواع غير المشروط من استنتاج الأنواع العامة&lt;/h2&gt;
&lt;p&gt;تُعد الأنواع العامة (Generics) والأنواع الشرطية (Conditional Types) من أقوى ميزات TypeScript، لكن استخدامها معًا يمكن أن يؤدي إلى سلوكيات غير متوقعة، مثل مشكلة تقاطع الأنواع غير المشروط (Unconditional Type Intersection).&lt;/p&gt;
&lt;h3&gt;فهم المشكلة&lt;/h3&gt;
&lt;p&gt;تحدث هذه المشكلة عندما يقوم TypeScript باستنتاج نوع عام بطريقة تؤدي إلى تقاطع غير مقصود للأنواع، خاصة في سياق الأنواع الشرطية الموزعة (Distributive Conditional Types). عندما يتم تطبيق نوع شرطي على نوع عام يمثل اتحادًا (Union)، فإنه يتوزع على أعضاء الاتحاد. ومع ذلك، إذا لم يتم التحكم في هذا التوزيع بعناية، فقد ينتهي بنا المطاف بتقاطع غير مرغوب فيه للنتائج.&lt;/p&gt;
&lt;pre data-comment='TypeScript' data-source='problem.ts'&gt;&lt;code&gt;type MyConditional&amp;lt;T&amp;gt; = T extends string ? { a: string } : { b: number };

// إذا كان T هو string | number، فإن MyConditional&amp;lt;T&amp;gt; سيوزع
// MyConditional&amp;lt;string&amp;gt; | MyConditional&amp;lt;number&amp;gt;
// وهو { a: string } | { b: number }

// ولكن في بعض السيناريوهات المعقدة، قد يتم استنتاج T كـ string &amp; number (never)
// أو قد يؤدي إلى تقاطع غير مقصود إذا كان T يستخدم في سياق آخر.

// مثال مبسط يوضح كيف يمكن أن يحدث تقاطع غير مقصود:
type IntersectIfString&amp;lt;T&amp;gt; = T extends string ? T &amp; { isString: true } : T;

function process&amp;lt;T&amp;gt;(value: T): IntersectIfString&amp;lt;T&amp;gt; {
  if (typeof value === 'string') {
    // هنا، TypeScript قد لا يضيق T إلى string بشكل كامل في سياق النوع العام
    // وقد ينتهي النوع المستنتج بـ T &amp; { isString: true } حتى لو كان T ليس string
    return { ...value as any, isString: true }; // مثال توضيحي
  }
  return value as IntersectIfString&amp;lt;T&amp;gt;;
}

const result = process(123); // المتوقع 123 (number)
// ولكن في سيناريوهات معقدة، قد يتم استنتاج نوع مثل number &amp; { isString: true } (never)
// أو قد يظهر سلوك غريب إذا كان التوزيع غير متحكم به.&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;تظهر هذه المشكلة بشكل أكثر شيوعًا عند التعامل مع أنواع عامة معقدة تتضمن أنواعًا شرطية متداخلة أو عند محاولة استنتاج أنواع بناءً على خصائص موجودة في كائنات ذات أنواع عامة.&lt;/p&gt;

&lt;h3&gt;التأثير والحلول&lt;/h3&gt;
&lt;p&gt;يؤثر هذا السلوك على سلامة الأنواع، حيث يمكن أن يؤدي إلى أنواع &lt;code&gt;never&lt;/code&gt; غير متوقعة أو أنواع تقاطع لا معنى لها، مما يجعل الكود أكثر عرضة للأخطاء في وقت التشغيل. لتشخيص هذه المشكلة، يمكن استخدام أدوات المطور في VS Code لتحليل الأنواع المستنتجة.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;منع التوزيع:&lt;/b&gt;
    &lt;p&gt;يمكن منع الأنواع الشرطية من التوزيع عن طريق تغليف النوع العام في مصفوفة (Tuple). على سبيل المثال، &lt;code&gt;[T] extends [U] ? ... : ...&lt;/code&gt; بدلاً من &lt;code&gt;T extends U ? ... : ...&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تحديد قيود عامة أكثر صرامة:&lt;/b&gt;
    &lt;p&gt;تضييق النطاق المحتمل للنوع العام &lt;code&gt;T&lt;/code&gt; باستخدام قيود &lt;code&gt;extends&lt;/code&gt; يمكن أن يساعد TypeScript على استنتاج الأنواع بشكل أكثر دقة.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استخدام أنواع مساعدة:&lt;/b&gt;
    &lt;p&gt;تقسيم الأنواع الشرطية المعقدة إلى أنواع مساعدة أصغر يمكن أن يجعل عملية الاستنتاج أكثر وضوحًا لـ TypeScript.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الاستنتاج الصريح:&lt;/b&gt;
    &lt;p&gt;في بعض الحالات، قد يكون من الضروري تحديد الأنواع بشكل صريح بدلاً من الاعتماد كليًا على الاستنتاج.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;فهم كيفية عمل استنتاج الأنواع الشرطية الموزعة أمر بالغ الأهمية لتجنب هذه المشكلة. تذكر أن &lt;code&gt;T extends U ? X : Y&lt;/code&gt; يتوزع على أعضاء الاتحاد &lt;code&gt;T&lt;/code&gt;، بينما &lt;code&gt;[T] extends [U] ? X : Y&lt;/code&gt; لا يتوزع.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما الفرق بين &lt;code&gt;readonly&lt;/code&gt; و &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;&lt;code&gt;readonly&lt;/code&gt; هو معدل يُطبق على خاصية واحدة داخل واجهة أو كلاس لجعلها غير قابلة للتعديل بعد التهيئة. أما &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt; فهو نوع مساعد (Utility Type) يأخذ نوعًا &lt;code&gt;T&lt;/code&gt; ويُنشئ نوعًا جديدًا تكون جميع خصائصه للقراءة فقط بشكل سطحي.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;كيف يمكنني حل خطأ &lt;code&gt;-991010&lt;/code&gt; في Angular إذا كنت أستخدم Webpack مخصصًا؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;إذا كنت تستخدم تكوين Webpack مخصصًا، فيجب عليك التأكد من أن Webpack يفهم تعيينات &lt;code&gt;paths&lt;/code&gt; في &lt;code&gt;tsconfig.json&lt;/code&gt;. يمكنك تحقيق ذلك عن طريق استخدام &lt;code&gt;TsConfigPathsPlugin&lt;/code&gt; من حزمة &lt;code&gt;tsconfig-paths-webpack-plugin&lt;/code&gt; في تكوين Webpack الخاص بك، أو عن طريق تكوين &lt;code&gt;alias&lt;/code&gt; يدويًا في قسم &lt;code&gt;resolve&lt;/code&gt; في Webpack.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هي إحدى الطرق الفعالة لمنع مشكلة تقاطع الأنواع غير المشروط في الأنواع الشرطية؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;إحدى الطرق الفعالة هي منع التوزيع (Distributivity) في الأنواع الشرطية. يمكنك القيام بذلك عن طريق تغليف النوع العام في مصفوفة (Tuple) عند استخدامه في الشرط، مثل &lt;code&gt;[T] extends [U] ? X : Y&lt;/code&gt; بدلاً من &lt;code&gt;T extends U ? X : Y&lt;/code&gt;. هذا يضمن أن النوع الشرطي لا يتوزع على أعضاء الاتحاد داخل &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/07/advanced-typescript-type-constraints.html'&gt;TypeScript: تحديات متقدمة في قيود الأنواع، حل الوحدات، واستنتاج العموميات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>معالجة أخطاء تثبيت Playwright: حلول عملية لـ npx playwright install</title><link>https://www.siwane.xyz/2026/07/playwright-install.html</link><category>مقالات AI</category><pubDate>Mon, 6 Jul 2026 10:27:51 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-1450884272779160968</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="معالجة أخطاء تثبيت Playwright: حلول عملية لـ npx playwright install" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;دليل شامل لحل مشكلات تثبيت Playwright الشائعة مثل أخطاء الشبكة، الأذونات، وإصدارات Node.js، مع خطوات عملية ومباشرة.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الويب الحديث، أصبحت أدوات الأتمتة والاختبار ضرورية لضمان جودة التطبيقات. Playwright، مكتبة أتمتة المتصفحات من Microsoft، تبرز كخيار قوي بفضل دعمها لمتصفحات متعددة وقدراتها المتقدمة. ومع ذلك، قد يواجه المطورون أحيانًا تحديات أثناء عملية التثبيت الأولية، خاصة عند تشغيل الأمر &lt;code&gt;npx playwright install&lt;/code&gt;. يهدف هذا المقال إلى تقديم حلول عملية ومباشرة لأكثر الأخطاء شيوعًا التي قد تواجهها، مما يضمن تجربة تثبيت سلسة.&lt;/p&gt;

&lt;h2 id="understanding-install-error"&gt;فهم مشكلة "npx playwright install"&lt;/h2&gt;
&lt;p&gt;عند تشغيل الأمر &lt;code&gt;npx playwright install&lt;/code&gt;، يقوم Playwright بتنزيل وتثبيت الثنائيات الخاصة بالمتصفحات (Chromium، Firefox، WebKit) التي يحتاجها لتشغيل الاختبارات. هذه العملية تتطلب اتصالاً مستقرًا بالإنترنت، وأذونات كافية للملفات، وإصدارًا متوافقًا من Node.js. يمكن أن تؤدي أي مشكلة في هذه المتطلبات إلى فشل التثبيت وظهور رسائل خطأ مختلفة.&lt;/p&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;Playwright لا يقوم بتثبيت المتصفحات الفعلية كنظام تشغيل، بل يقوم بتنزيل نسخ مخصصة ومحسّنة للاستخدام مع Playwright.&lt;/p&gt;

&lt;h2 id="practical-solutions"&gt;حلول عملية لمشكلة التثبيت&lt;/h2&gt;

&lt;h3 id="check-nodejs-npm"&gt;التحقق من إصدار Node.js و npm&lt;/h3&gt;
&lt;p&gt;يتطلب Playwright إصدارات حديثة من Node.js و npm ليعمل بشكل صحيح. قد يؤدي استخدام إصدار قديم إلى مشكلات في التوافق أو أخطاء أثناء التثبيت.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;التحقق من الإصدارات الحالية:&lt;/b&gt;
    &lt;pre data-comment='الطرفية' data-source='التحقق من الإصدارات'&gt;&lt;code&gt;node -v
npm -v&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تحديث Node.js و npm:&lt;/b&gt;
    &lt;p&gt;إذا كانت الإصدارات قديمة، يوصى بتحديثها. يمكنك استخدام مدير الإصدارات مثل &lt;a class='extL' href='https://github.com/nvm-sh/nvm' rel='nofollow noreferrer' target='_blank'&gt;NVM&lt;/a&gt; (Node Version Manager) أو &lt;a class='extL' href='https://github.com/tj/n' rel='nofollow noreferrer' target='_blank'&gt;n&lt;/a&gt;.&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='تحديث Node.js باستخدام n'&gt;&lt;code&gt;npm install -g n
sudo n latest&lt;/code&gt;&lt;/pre&gt;
    &lt;p&gt;أو باستخدام NVM:&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='تحديث Node.js باستخدام NVM'&gt;&lt;code&gt;nvm install node
nvm use node&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="network-proxy-issues"&gt;معالجة مشكلات الشبكة والوكيل (Proxy)&lt;/h3&gt;
&lt;p&gt;تُعد مشكلات الاتصال بالشبكة من الأسباب الشائعة لفشل التنزيل. قد تكون جدار الحماية (Firewall)، أو الشبكات الافتراضية الخاصة (VPN)، أو خوادم الوكيل (Proxy) في بيئات الشركات هي السبب.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;تعطيل مؤقت لجدار الحماية/VPN:&lt;/b&gt;
    &lt;p&gt;حاول تعطيل جدار الحماية أو VPN مؤقتًا ثم أعد تشغيل أمر التثبيت.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تكوين إعدادات الوكيل:&lt;/b&gt;
    &lt;p&gt;إذا كنت تستخدم خادم وكيل، تأكد من تكوينه بشكل صحيح لـ npm ولبيئة التشغيل:&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='إعداد الوكيل'&gt;&lt;code&gt;export HTTP_PROXY="http://your.proxy.com:port"
export HTTPS_PROXY="http://your.proxy.com:port"
npm config set proxy http://your.proxy.com:port
npm config set https-proxy http://your.proxy.com:port&lt;/code&gt;&lt;/pre&gt;
    &lt;p&gt;في نظام Windows، استخدم &lt;code&gt;set&lt;/code&gt; بدلاً من &lt;code&gt;export&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تحديد مضيف تنزيل Playwright:&lt;/b&gt;
    &lt;p&gt;في بعض الحالات، قد تحتاج إلى تحديد مضيف تنزيل Playwright يدويًا إذا كانت هناك مشكلات في الوصول إلى الخوادم الافتراضية:&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='تحديد مضيف التنزيل'&gt;&lt;code&gt;export PLAYWRIGHT_DOWNLOAD_HOST="https://playwright.azureedge.net"&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="file-permissions"&gt;أذونات الملفات والمجلدات&lt;/h3&gt;
&lt;p&gt;يمكن أن تظهر أخطاء الأذونات (مثل &lt;code&gt;EACCES&lt;/code&gt;) إذا لم يكن لدى المستخدم الحالي الصلاحيات الكافية لكتابة الملفات في مجلدات النظام أو مجلدات npm.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;استخدام &lt;code&gt;sudo&lt;/code&gt; (لأنظمة Linux/macOS):&lt;/b&gt;
    &lt;p&gt;حاول تشغيل الأمر بصلاحيات المدير:&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='التثبيت بصلاحيات المدير'&gt;&lt;code&gt;sudo npx playwright install&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تكوين &lt;code&gt;unsafe-perm&lt;/code&gt; (بحذر):&lt;/b&gt;
    &lt;p&gt;يمكنك تجاوز مشكلات الأذونات عن طريق تعيين &lt;code&gt;unsafe-perm&lt;/code&gt; إلى &lt;code&gt;true&lt;/code&gt; في npm، ولكن هذا يقلل من الأمان.&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='إعداد unsafe-perm'&gt;&lt;code&gt;npm config set unsafe-perm true&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;استخدام &lt;code&gt;unsafe-perm true&lt;/code&gt; قد يقلل من أمان نظامك. استخدمه بحذر وفقط إذا كنت تفهم المخاطر.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="clear-npm-cache"&gt;مسح ذاكرة التخزين المؤقت لـ npm&lt;/h3&gt;
&lt;p&gt;قد تتسبب ذاكرة التخزين المؤقت لـ npm التالفة أو القديمة في حدوث أخطاء أثناء التثبيت.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;مسح ذاكرة التخزين المؤقت:&lt;/b&gt;
    &lt;pre data-comment='الطرفية' data-source='مسح ذاكرة التخزين المؤقت'&gt;&lt;code&gt;npm cache clean --force&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إعادة المحاولة:&lt;/b&gt;
    &lt;p&gt;بعد مسح ذاكرة التخزين المؤقت، أعد تشغيل أمر التثبيت:&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='إعادة التثبيت'&gt;&lt;code&gt;npx playwright install&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="reinstall-playwright"&gt;إعادة تثبيت Playwright&lt;/h3&gt;
&lt;p&gt;في بعض الأحيان، قد يكون هناك تلف في تثبيت Playwright نفسه. يمكن أن تساعد إعادة التثبيت النظيفة في حل المشكلة.&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;إلغاء تثبيت Playwright:&lt;/b&gt;
    &lt;pre data-comment='الطرفية' data-source='إلغاء التثبيت'&gt;&lt;code&gt;npm uninstall playwright&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إعادة تثبيت Playwright:&lt;/b&gt;
    &lt;pre data-comment='الطرفية' data-source='إعادة التثبيت'&gt;&lt;code&gt;npm install playwright&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تثبيت المتصفحات:&lt;/b&gt;
    &lt;pre data-comment='الطرفية' data-source='تثبيت المتصفحات'&gt;&lt;code&gt;npx playwright install&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="manual-browser-install"&gt;تثبيت المتصفحات يدوياً مع التبعيات&lt;/h3&gt;
&lt;p&gt;إذا استمرت المشكلات، يمكنك محاولة تثبيت المتصفحات بشكل صريح، مع التأكد من تثبيت تبعيات النظام (خاصة في أنظمة Linux).&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;تثبيت المتصفحات مع تبعيات النظام (لأنظمة Linux):&lt;/b&gt;
    &lt;pre data-comment='الطرفية' data-source='تثبيت مع التبعيات'&gt;&lt;code&gt;npx playwright install --with-deps&lt;/code&gt;&lt;/pre&gt;
    &lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;الخيار &lt;code&gt;--with-deps&lt;/code&gt; يقوم بتثبيت تبعيات نظام التشغيل المطلوبة لتشغيل المتصفحات (مثل مكتبات الرسوميات).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تثبيت متصفحات محددة:&lt;/b&gt;
    &lt;p&gt;إذا كنت تحتاج فقط إلى متصفحات معينة، يمكنك تحديدها:&lt;/p&gt;
    &lt;pre data-comment='الطرفية' data-source='تثبيت متصفحات محددة'&gt;&lt;code&gt;npx playwright install chromium firefox webkit&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="check-disk-space"&gt;التحقق من مساحة القرص&lt;/h3&gt;
&lt;p&gt;تتطلب ثنائيات المتصفحات مساحة تخزين كبيرة. تأكد من وجود مساحة كافية على القرص الصلب قبل محاولة التثبيت.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
  &lt;p&gt;&lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;بعد تطبيق أي من هذه الحلول، يوصى دائمًا بإعادة تشغيل الطرفية أو بيئة التطوير قبل محاولة التثبيت مرة أخرى لضمان تطبيق جميع التغييرات في المتغيرات البيئية أو الإعدادات.&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id="conclusion"&gt;الخاتمة&lt;/h2&gt;
&lt;p&gt;تُعد أخطاء التثبيت جزءًا طبيعيًا من عملية تطوير البرمجيات، وفهم الأسباب الجذرية لها هو مفتاح الحل. من خلال اتباع الخطوات المذكورة أعلاه، يمكنك معالجة معظم المشكلات المتعلقة بـ &lt;code&gt;npx playwright install&lt;/code&gt; واستئناف عملك في أتمتة الويب بثقة. تذكر دائمًا التحقق من وثائق Playwright الرسمية للحصول على أحدث المعلومات وأكثرها تفصيلاً.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;لماذا يفشل أمر &lt;code&gt;npx playwright install&lt;/code&gt; عادة؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;يفشل هذا الأمر عادة بسبب مشكلات في الاتصال بالشبكة (جدار الحماية، الوكيل)، أو أذونات الملفات غير الكافية، أو إصدار Node.js غير المتوافق، أو ذاكرة التخزين المؤقت لـ npm التالفة.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ماذا يفعل الخيار &lt;code&gt;--with-deps&lt;/code&gt; عند تثبيت Playwright؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;الخيار &lt;code&gt;--with-deps&lt;/code&gt; (المتاح بشكل أساسي لأنظمة Linux) يقوم بتثبيت تبعيات نظام التشغيل الإضافية المطلوبة لتشغيل المتصفحات، مثل مكتبات الرسوميات، والتي لا يتم تضمينها عادةً في تثبيت Playwright الأساسي.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/07/playwright-install.html'&gt;معالجة أخطاء تثبيت Playwright: حلول عملية لـ npx playwright install&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>معالجة مشكلة Node.js: تجميد مطابقة الملفات الديناميكية في الحلقات غير المتزامنة</title><link>https://www.siwane.xyz/2026/06/nodejs.html</link><category>مقالات AI</category><pubDate>Mon, 29 Jun 2026 10:27:46 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-6878939765629975854</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="معالجة مشكلة Node.js: تجميد مطابقة الملفات الديناميكية في الحلقات غير المتزامنة" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;تجميد Node.js بسبب مطابقة الملفات الديناميكية في الحلقات غير المتزامنة يؤثر على أداء العمال. اكتشف حلولاً عملية لتجنب هذا الخلل.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; بيئات Node.js، قد يواجه المطورون تحديات خطيرة عند التعامل مع مطابقة الملفات الديناميكية بناءً على مدخلات المستخدم ضمن حلقات غير متزامنة. يمكن أن يؤدي هذا السيناريو إلى تجميد التطبيق أو تشغيل جميع العمال في نفس الوقت، مما يؤثر بشكل كبير على الأداء واستجابة النظام. يستكشف هذا المقال الأسباب الجذرية لهذه المشكلة ويقدم حلولاً عملية لتجاوزها.&lt;/p&gt;

&lt;h2 id="the-root-cause-of-the-problem"&gt;السبب الجذري للمشكلة&lt;/h2&gt;
&lt;p&gt;تنشأ مشكلة التجميد أو التشغيل المتزامن لجميع العمال عادةً من مزيج من العوامل:&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;العمليات المتزامنة في حلقة الحدث:&lt;/b&gt; على الرغم من أن Node.js يعتمد على نموذج I/O غير المحظور، إلا أن بعض العمليات مثل قراءة الملفات الكبيرة بشكل متزامن (باستخدام &lt;code&gt;fs.readFileSync&lt;/code&gt;) أو تنفيذ تعبيرات منتظمة (Regex) معقدة على سلاسل نصية طويلة، يمكن أن تحظر حلقة الحدث (Event Loop) وتجعل التطبيق غير مستجيب.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الحلقات غير المتزامنة غير الفعالة:&lt;/b&gt; عند استخدام حلقات غير متزامنة مثل &lt;code&gt;for...of&lt;/code&gt; مع &lt;code&gt;await&lt;/code&gt; داخلها، أو &lt;code&gt;Promise.all&lt;/code&gt; مع عدد كبير من الوعود التي تتضمن عمليات I/O مكثفة أو معالجة بيانات، يمكن أن يؤدي ذلك إلى استنزاف موارد النظام إذا لم يتم التعامل معها بكفاءة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;مطابقة الملفات الديناميكية:&lt;/b&gt; تتطلب مطابقة الملفات الديناميكية (مثل البحث عن ملفات تطابق نمط معين بناءً على إدخال المستخدم) الوصول إلى نظام الملفات (File System) بشكل متكرر، وهو ما يمكن أن يكون مكلفاً من حيث الأداء.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;نموذج العامل الواحد (Single-Threaded Model):&lt;/b&gt; على الرغم من وجود وحدات مثل &lt;code&gt;cluster&lt;/code&gt; و &lt;code&gt;worker_threads&lt;/code&gt;، فإن Node.js في جوهره يعمل على خيط واحد (Single Thread) لحلقة الحدث. أي عملية تحظر هذا الخيط ستؤثر على استجابة التطبيق بأكمله.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="practical-solutions"&gt;حلول عملية&lt;/h2&gt;

&lt;h3 id="offloading-heavy-tasks-with-worker-threads"&gt;1. تفريغ المهام الثقيلة باستخدام Worker Threads&lt;/h3&gt;
&lt;p&gt;لحل مشكلة حظر حلقة الحدث، يمكن نقل العمليات كثيفة الاستخدام لوحدة المعالجة المركزية (CPU-intensive) مثل مطابقة التعبيرات المنتظمة المعقدة أو عمليات I/O المكثفة إلى &lt;b style='color:var(--linkC)'&gt;Worker Threads&lt;/b&gt;. يسمح ذلك لحلقة الحدث الرئيسية بالبقاء حرة ومستجيبة.&lt;/p&gt;
&lt;pre data-comment='Worker Thread' data-source='worker.js'&gt;&lt;code&gt;
const { parentPort } = require('worker_threads');
const fs = require('fs').promises;
const path = require('path');

parentPort.on('message', async ({ directory, pattern }) =&gt; {
  try {
    const files = await fs.readdir(directory);
    const regex = new RegExp(pattern, 'i'); // 'i' for case-insensitive
    const matchedFiles = files.filter(file =&gt; regex.test(file));
    parentPort.postMessage({ status: 'success', matchedFiles });
  } catch (error) {
    parentPort.postMessage({ status: 'error', message: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre data-comment='Main Thread' data-source='main.js'&gt;&lt;code&gt;
const { Worker } = require('worker_threads');

async function findFiles(directory, pattern) {
  return new Promise((resolve, reject) =&gt; {
    const worker = new Worker('./worker.js');
    worker.postMessage({ directory, pattern });
    worker.on('message', (message) =&gt; {
      if (message.status === 'success') {
        resolve(message.matchedFiles);
      } else {
        reject(new Error(message.message));
      }
      worker.terminate();
    });
    worker.on('error', reject);
    worker.on('exit', (code) =&gt; {
      if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
    });
  });
}

// Example usage
// findFiles('/path/to/search', 'user_input_pattern')
//   .then(files =&gt; console.log('Matched files:', files))
//   .catch(err =&gt; console.error('Error:', err));
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="asynchronous-file-io"&gt;2. استخدام I/O غير المتزامن للملفات&lt;/h3&gt;
&lt;p&gt;تأكد دائماً من استخدام واجهات برمجة تطبيقات &lt;b style='color:var(--linkC)'&gt;I/O غير المتزامنة&lt;/b&gt; للملفات (مثل &lt;code&gt;fs.promises&lt;/code&gt;) لتجنب حظر حلقة الحدث. تجنب &lt;code&gt;fs.readFileSync&lt;/code&gt; و &lt;code&gt;fs.readdirSync&lt;/code&gt; في سياقات الويب أو التطبيقات التي تتطلب استجابة عالية.&lt;/p&gt;
&lt;pre data-comment='Async File Read' data-source='asyncFile.js'&gt;&lt;code&gt;
const fs = require('fs').promises;

async function getFileContent(filePath) {
  try {
    const content = await fs.readFile(filePath, 'utf8');
    return content;
  } catch (error) {
    console.error(`Failed to read file ${filePath}:`, error);
    throw error;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="efficient-file-matching"&gt;3. مطابقة الملفات بكفاءة&lt;/h3&gt;
&lt;p&gt;بدلاً من قراءة جميع الملفات ثم تطبيق التعبير المنتظم، فكر في استراتيجيات أكثر كفاءة:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;استخدام مكتبات Glob:&lt;/b&gt; مكتبات مثل &lt;a class='extL' href='https://www.npmjs.com/package/fast-glob' rel='nofollow noreferrer' target='_blank'&gt;&lt;code&gt;fast-glob&lt;/code&gt;&lt;/a&gt; يمكنها التعامل مع أنماط المطابقة المعقدة بكفاءة عالية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;الفهرسة المسبقة (Pre-indexing):&lt;/b&gt; إذا كانت قائمة الملفات لا تتغير كثيراً، يمكنك فهرسة أسمائها مسبقاً في الذاكرة أو قاعدة بيانات لعمليات البحث السريعة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تحسين التعبيرات المنتظمة:&lt;/b&gt; تأكد من أن التعبيرات المنتظمة التي تستخدمها محسّنة ولا تتسبب في &lt;b style='color:var(--linkC)'&gt;ReDoS (Regular Expression Denial of Service)&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="debouncing-user-input"&gt;4. Debouncing لمدخلات المستخدم&lt;/h3&gt;
&lt;p&gt;إذا كانت مطابقة الملفات يتم تشغيلها بواسطة إدخال المستخدم (مثل حقل بحث)، فاستخدم تقنية &lt;b style='color:var(--linkC)'&gt;Debouncing&lt;/b&gt; لتقليل عدد مرات تشغيل عملية البحث. هذا يمنع إرسال طلبات متعددة في وقت قصير جداً.&lt;/p&gt;
&lt;pre data-comment='Debounce Function' data-source='debounce.js'&gt;&lt;code&gt;
function debounce(func, delay) {
  let timeout;
  return function(...args) {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() =&gt; func.apply(context, args), delay);
  };
}

// Example usage in a web context (conceptual)
// const searchInput = document.getElementById('searchBox');
// searchInput.addEventListener('keyup', debounce(async (event) =&gt; {
//   const searchTerm = event.target.value;
//   // Trigger file matching logic here
//   console.log('Searching for:', searchTerm);
// }, 300));
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="caching-results"&gt;5. تخزين النتائج مؤقتاً (Caching)&lt;/h3&gt;
&lt;p&gt;إذا كانت عمليات البحث عن الملفات المتكررة لنفس النمط أو في نفس الدليل تعطي نفس النتائج، ففكر في &lt;b style='color:var(--linkC)'&gt;تخزين النتائج مؤقتاً&lt;/b&gt;. يمكن أن يقلل هذا بشكل كبير من حمل I/O على نظام الملفات.&lt;/p&gt;
&lt;pre data-comment='Simple Cache' data-source='cache.js'&gt;&lt;code&gt;
const fileMatchCache = new Map(); // Store results: Map&lt;pattern, matchedFiles[]&gt;

async function getCachedMatchedFiles(directory, pattern) {
  const cacheKey = `${directory}:${pattern}`;
  if (fileMatchCache.has(cacheKey)) {
    console.log('Returning from cache:', cacheKey);
    return fileMatchCache.get(cacheKey);
  }

  // If not in cache, perform the search (e.g., using a worker thread)
  const matchedFiles = await findFiles(directory, pattern); // findFiles from worker example
  fileMatchCache.set(cacheKey, matchedFiles);
  return matchedFiles;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;تأكد من تطبيق سياسة إبطال ذاكرة التخزين المؤقت (Cache Invalidation) إذا كانت الملفات في الدليل تتغير بشكل متكرر.&lt;/p&gt;

&lt;h3 id="limiting-concurrent-operations"&gt;6. تحديد العمليات المتزامنة&lt;/h3&gt;
&lt;p&gt;عند التعامل مع عدد كبير من الملفات أو المهام، استخدم أدوات مثل &lt;a class='extL' href='https://www.npmjs.com/package/p-limit' rel='nofollow noreferrer' target='_blank'&gt;&lt;code&gt;p-limit&lt;/code&gt;&lt;/a&gt; أو &lt;a class='extL' href='https://www.npmjs.com/package/p-queue' rel='nofollow noreferrer' target='_blank'&gt;&lt;code&gt;p-queue&lt;/code&gt;&lt;/a&gt; للتحكم في عدد العمليات غير المتزامنة التي تعمل في وقت واحد. هذا يمنع استنزاف موارد النظام.&lt;/p&gt;
&lt;pre data-comment='p-limit example' data-source='limit.js'&gt;&lt;code&gt;
const pLimit = require('p-limit');
const limit = pLimit(5); // Allow up to 5 concurrent operations

async function processFile(filePath) {
  // Simulate heavy file processing
  await new Promise(resolve =&gt; setTimeout(resolve, 100)); 
  return `Processed: ${filePath}`;
}

async function processAllFiles(filePaths) {
  const tasks = filePaths.map(filePath =&gt; limit(() =&gt; processFile(filePath)));
  const results = await Promise.all(tasks);
  return results;
}

// Example usage:
// processAllFiles(['file1.txt', 'file2.txt', ..., 'fileN.txt'])
//   .then(results =&gt; console.log(results));
&lt;/code&gt;&lt;/pre&gt;

&lt;div class='alert info outline'&gt;
  &lt;p&gt;&lt;b&gt;ملخص:&lt;/b&gt; لمعالجة مشكلة تجميد Node.js بسبب مطابقة الملفات الديناميكية، يجب التركيز على تفريغ المهام كثيفة الاستخدام لوحدة المعالجة المركزية، واستخدام I/O غير المتزامن، وتحسين خوارزميات المطابقة، وتطبيق تقنيات مثل Debouncing والتخزين المؤقت، وتحديد العمليات المتزامنة.&lt;/p&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/06/nodejs.html'&gt;معالجة مشكلة Node.js: تجميد مطابقة الملفات الديناميكية في الحلقات غير المتزامنة&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>Docker: ضمان استمرارية نشر الوسائط على AWS ومنع الأعطال</title><link>https://www.siwane.xyz/2026/06/docker-aws-media.html</link><category>مقالات AI</category><pubDate>Mon, 22 Jun 2026 10:27:56 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-5731922730352808137</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="Docker: ضمان استمرارية نشر الوسائط على AWS ومنع الأعطال" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;تجنب تعارضات بيئات النشر على AWS باستخدام Docker. مقال يقدم حلولاً عملية لضمان استمرارية نشر الوسائط ومنع الأعطال الناتجة عن اختلاف البيئات.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;إن&lt;/span&gt; مشكلة "المشارك الأول يعمل، والمشارك الثاني يعطل نشر الوسائط على AWS" هي سيناريو كلاسيكي لمتلازمة "يعمل على جهازي". غالباً ما تنبع هذه المشكلة من تناقضات بيئية، حيث تختلف التبعيات، التكوينات، أو إعدادات نظام التشغيل الأساسية بين بيئات التطوير وإعداد AWS الإنتاجي، أو حتى بين أجهزة المطورين المختلفين. يقدم Docker حلاً قوياً من خلال تغليف التطبيقات وتبعاتها في حاويات محمولة ومعزولة، مما يضمن بيئة تنفيذ متسقة عبر جميع المراحل والمشاركين.&lt;/p&gt;

&lt;h2 id="problem-analysis"&gt;تحليل المشكلة&lt;/h2&gt;
&lt;p&gt;تعاني طرق النشر التقليدية في كثير من الأحيان من:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;b&gt;جحيم التبعيات (Dependency Hell):&lt;/b&gt; قد تتعارض الإصدارات المختلفة من المكتبات أو أوقات التشغيل المطلوبة بواسطة مكونات متنوعة.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;انحراف البيئة (Environment Drift):&lt;/b&gt; لا يتم تكرار التكوينات أو التحديثات اليدوية على جهاز واحد على الأجهزة الأخرى.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;عدم اتساق الأدوات:&lt;/b&gt; قد يستخدم المطورون إصدارات مختلفة من أدوات البناء، المترجمات، أو أنظمة التشغيل.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;عدم تطابق التكوين:&lt;/b&gt; قد تختلف متغيرات البيئة، مسارات الملفات، أو سلاسل اتصال قاعدة البيانات.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;تصبح هذه التناقضات حرجة في نشر الوسائط، حيث يجب تكوين برامج ترميز معينة، مكتبات، أو أدوات معالجة بدقة لتعمل بشكل صحيح. يمكن أن يؤدي أي انحراف طفيف إلى فشل عمليات التحويل، أو تحميلات معطلة، أو محتوى غير قابل للوصول.&lt;/p&gt;

&lt;h2 id="docker-as-solution"&gt;Docker كحل جذري&lt;/h2&gt;
&lt;p&gt;يعالج Docker هذه التحديات من خلال مفهوم الحاويات:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;b&gt;التغليف:&lt;/b&gt; يتم تجميع التطبيق، جنباً إلى جنب مع جميع مكتباته، تبعياته، وملفات التكوين الخاصة به، في صورة Docker واحدة.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;العزل:&lt;/b&gt; تعمل كل حاوية في بيئتها المعزولة الخاصة بها، مما يمنع التعارضات مع التطبيقات الأخرى أو النظام المضيف.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;قابلية النقل:&lt;/b&gt; يمكن تشغيل نفس صورة Docker بشكل متسق على أي نظام مثبت عليه Docker، سواء كان جهاز كمبيوتر محمول للمطور، خادم اختبار، أو مثيل إنتاج على AWS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class='pIndent'&gt;هذا يعني أنه إذا قام المشارك الأول بنشر الوسائط بنجاح باستخدام تطبيق Dockerized، فسيستخدم المشارك الثاني نفس صورة Docker بالضبط، مما يضمن نفس البيئة ويمنع الأعطال غير المتوقعة.&lt;/p&gt;

&lt;h2 id="practical-implementation"&gt;خطوات التنفيذ العملي لنشر الوسائط على AWS&lt;/h2&gt;
&lt;ol class="steps"&gt;
    &lt;li&gt;
        &lt;b&gt;تحديد متطلبات التطبيق:&lt;/b&gt;
        حدد جميع التبعيات، مكتبات الوسائط (مثل FFmpeg)، إصدارات وقت التشغيل (مثل Node.js، Python)، وأي أدوات مساعدة يحتاجها تطبيق نشر الوسائط.
    &lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;إنشاء Dockerfile:&lt;/b&gt;
        اكتب &lt;code&gt;Dockerfile&lt;/code&gt; لتحديد كيفية بناء صورة Docker لتطبيقك. يجب أن يتضمن هذا تثبيت جميع التبعيات، نسخ كود التطبيق، وتحديد أمر التشغيل.
        &lt;pre data-comment='Dockerfile' data-source='Dockerfile'&gt;&lt;code&gt;
# استخدم صورة أساسية مناسبة (مثلاً، Node.js أو Python)
FROM node:18-alpine

# تعيين دليل العمل داخل الحاوية
WORKDIR /app

# نسخ ملفات تعريف التبعيات وتثبيتها
COPY package.json package-lock.json ./
RUN npm install

# تثبيت FFmpeg (مثال لتطبيق وسائط)
RUN apk add --no-cache ffmpeg

# نسخ كود التطبيق
COPY . .

# تعريض المنفذ الذي يستمع إليه التطبيق
EXPOSE 3000

# أمر تشغيل التطبيق
CMD ["npm", "start"]
        &lt;/code&gt;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;بناء صورة Docker:&lt;/b&gt;
        قم ببناء الصورة محلياً للتأكد من أنها تعمل كما هو متوقع.
        &lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code&gt;
&lt;mark class='green' data-before='$'&gt;docker build -t media-publisher:latest .&lt;/mark&gt;
        &lt;/code&gt;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;اختبار الصورة محلياً:&lt;/b&gt;
        شغل الحاوية محلياً واختبر وظائف نشر الوسائط.
        &lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code&gt;
&lt;mark class='green' data-before='$'&gt;docker run -p 3000:3000 media-publisher:latest&lt;/mark&gt;
        &lt;/code&gt;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;دفع الصورة إلى Amazon ECR:&lt;/b&gt;
        بعد التأكد من أن الصورة تعمل، قم بإنشاء مستودع في &lt;b style='color:var(--linkC)'&gt;Amazon Elastic Container Registry (ECR)&lt;/b&gt; وادفع الصورة إليه. هذا يضمن أن جميع المشاركين وبيئات AWS يمكنهم الوصول إلى نفس الصورة الموثوقة.
        &lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code&gt;
&lt;mark class='green' data-before='$'&gt;aws ecr get-login-password --region your-region | docker login --username AWS --password-stdin your-aws-account-id.dkr.ecr.your-region.amazonaws.com&lt;/mark&gt;
&lt;mark class='green' data-before='$'&gt;docker tag media-publisher:latest your-aws-account-id.dkr.ecr.your-region.amazonaws.com/media-publisher:latest&lt;/mark&gt;
&lt;mark class='green' data-before='$'&gt;docker push your-aws-account-id.dkr.ecr.your-region.amazonaws.com/media-publisher:latest&lt;/mark&gt;
        &lt;/code&gt;&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
        &lt;b&gt;النشر على AWS ECS أو EKS:&lt;/b&gt;
        استخدم &lt;b style='color:var(--linkC)'&gt;Amazon Elastic Container Service (ECS)&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;Amazon Elastic Kubernetes Service (EKS)&lt;/b&gt; لنشر وإدارة الحاويات. قم بإنشاء تعريف مهمة (Task Definition) في ECS أو ملف نشر (Deployment) في EKS يشير إلى صورة Docker المخزنة في ECR.
        &lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;استخدم متغيرات البيئة (Environment Variables) في تعريف مهمة ECS أو ملف نشر EKS لإدارة الإعدادات الخاصة بالبيئة (مثل مفاتيح API، عناوين URL لقواعد البيانات) دون تعديل الصورة نفسها.&lt;/p&gt;
    &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;من خلال هذه الخطوات، يتم توحيد بيئة نشر الوسائط. عندما يعمل مشارك جديد على المشروع، فإنه يسحب نفس صورة Docker من ECR، مما يضمن أن لديه نفس الإعدادات والتبعيات التي عملت للمشارك الأول، وبالتالي يمنع الأعطال الناتجة عن عدم التوافق البيئي.&lt;/p&gt;

&lt;div class='alert success outline'&gt;
    &lt;b&gt;الفوائد الرئيسية:&lt;/b&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;b&gt;التناسق:&lt;/b&gt; بيئة تشغيل متطابقة عبر جميع مراحل التطوير والاختبار والإنتاج.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;العزل:&lt;/b&gt; منع تعارضات التبعيات بين التطبيقات المختلفة.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;السرعة:&lt;/b&gt; تسريع عملية الإعداد للمطورين الجدد وتقليل وقت حل المشكلات البيئية.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;الموثوقية:&lt;/b&gt; تقليل احتمالية حدوث أخطاء "يعمل على جهازي" بشكل كبير.&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;

&lt;h2 id="conclusion"&gt;الخاتمة&lt;/h2&gt;
&lt;p&gt;إن مشكلة "المشارك الأول يعمل، والمشارك الثاني يعطل نشر الوسائط على AWS" هي عَرَض كلاسيكي لغياب التوحيد البيئي. يوفر Docker حلاً قوياً وفعالاً لهذه المشكلة من خلال تمكين فرق العمل من بناء ونشر تطبيقاتهم في بيئات معزولة ومتسقة. من خلال تبني ممارسات Docker، يمكن للمؤسسات ضمان استمرارية عمليات نشر الوسائط على AWS، وتقليل وقت التوقف عن العمل، وتحسين كفاءة فريق التطوير بشكل كبير.&lt;/p&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هو Docker وما فائدته في هذا السيناريو؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;Docker هو منصة لإنشاء وتشغيل وإدارة الحاويات. في هذا السيناريو، يسمح Docker بتغليف تطبيق نشر الوسائط وجميع تبعياته في "صورة" واحدة، مما يضمن أن البيئة التي يعمل فيها التطبيق متطابقة تماماً عبر جميع المطورين وبيئات النشر على AWS، وبالتالي يمنع الأعطال الناتجة عن اختلاف البيئات.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل Docker معقد للمطورين الجدد؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;قد يتطلب Docker منحنى تعلم أولياً، لكن الفوائد التي يقدمها من حيث التناسق والتبسيط في الإعداد تفوق التعقيد الأولي. بمجرد إعداد &lt;code&gt;Dockerfile&lt;/code&gt; وصورة التطبيق، يصبح تشغيل التطبيق للمطورين الجدد أمراً بسيطاً للغاية باستخدام أمر &lt;code&gt;docker run&lt;/code&gt; واحد، مما يقلل بشكل كبير من مشاكل إعداد البيئة.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt;
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/06/docker-aws-media.html'&gt;Docker: ضمان استمرارية نشر الوسائط على AWS ومنع الأعطال&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>React.js و TypeScript: التوافق الأمثل لتطوير الواجهة الأمامية</title><link>https://www.siwane.xyz/2026/06/react-typescript-optimal-frontend.html</link><category>مقالات AI</category><pubDate>Fri, 19 Jun 2026 22:33:54 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-418670673342779825</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="React.js و TypeScript: التوافق الأمثل لتطوير الواجهة الأمامية" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;اكتشف كيف يعزز دمج React.js و TypeScript جودة الكود، ويحسن تجربة المطور، ويدعم قابلية الصيانة والتوسع في مشاريع الواجهة الأمامية.&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;صِوان AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;



&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الواجهة الأمامية سريع التطور، يبحث المطورون باستمرار عن الأدوات والتقنيات التي تعزز الكفاءة، وتحسن جودة الكود، وتضمن قابلية الصيانة على المدى الطويل. من بين هذه الأدوات، يبرز التوافق بين مكتبة React.js وإطار عمل TypeScript كحل قوي يقدم مزايا لا تقدر بثمن. يهدف هذا المقال إلى تحليل معمق لكيفية تحقيق هذا التوافق للمزايا القصوى في تطوير الواجهة الأمامية.&lt;/p&gt;

&lt;h2 id="what-is-reactjs"&gt;ما هو React.js؟&lt;/h2&gt;
&lt;p&gt;React.js هي مكتبة جافاسكريبت مفتوحة المصدر لبناء واجهات المستخدم، تم تطويرها بواسطة فيسبوك. تشتهر React بنهجها القائم على المكونات (Component-Based Architecture)، والذي يسمح للمطورين بتقسيم واجهة المستخدم إلى أجزاء صغيرة ومستقلة وقابلة لإعادة الاستخدام. هذا النهج يبسط عملية التطوير ويجعل إدارة واجهات المستخدم المعقدة أسهل بكثير. تعتمد React على مفهوم "الواجهة الافتراضية" (Virtual DOM) لتحسين الأداء، حيث تقوم بتحديث الأجزاء الضرورية فقط من الواجهة عند حدوث تغييرات.&lt;/p&gt;

&lt;h2 id="what-is-typescript"&gt;ما هو TypeScript؟&lt;/h2&gt;
&lt;p&gt;TypeScript هي لغة برمجة مفتوحة المصدر تم تطويرها وصيانتها بواسطة مايكروسوفت. إنها مجموعة شاملة من جافاسكريبت (Superset of JavaScript)، مما يعني أن أي كود جافاسكريبت صالح هو أيضًا كود TypeScript صالح. الميزة الأساسية لـ TypeScript هي إضافة نظام الأنواع الثابتة (Static Typing) إلى جافاسكريبت. هذا يسمح للمطورين بتحديد أنواع المتغيرات، والدوال، وخصائص الكائنات أثناء مرحلة التطوير، مما يساعد على اكتشاف الأخطاء المحتملة قبل تشغيل الكود.&lt;/p&gt;

&lt;h2 id="why-combine-react-typescript"&gt;لماذا ندمج React.js و TypeScript؟&lt;/h2&gt;
&lt;p&gt;دمج React.js مع TypeScript ليس مجرد خيار، بل أصبح معيارًا صناعيًا للعديد من المشاريع الكبيرة والمعقدة. هذا التوافق يوفر مجموعة من الفوائد التي تعزز تجربة التطوير وجودة المنتج النهائي.&lt;/p&gt;

&lt;h3 id="enhanced-code-quality"&gt;جودة الكود المحسنة&lt;/h3&gt;
&lt;p&gt;يعد نظام الأنواع الثابتة في TypeScript حجر الزاوية في تحسين جودة الكود. عند استخدام TypeScript مع React، يمكن للمطورين تحديد أنواع الخصائص (props) والحالة (state) للمكونات بدقة. هذا يقلل بشكل كبير من الأخطاء الشائعة التي تحدث بسبب عدم تطابق الأنواع أو تمرير بيانات غير متوقعة بين المكونات.&lt;/p&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;يساعد TypeScript في اكتشاف الأخطاء في وقت الترجمة (compile-time) بدلاً من وقت التشغيل (runtime)، مما يوفر الوقت والجهد في تصحيح الأخطاء.&lt;/p&gt;

&lt;h3 id="improved-developer-experience"&gt;تجربة مطور أفضل&lt;/h3&gt;
&lt;p&gt;يوفر TypeScript ميزات قوية لتحسين تجربة المطور (Developer Experience):&lt;/p&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;الإكمال التلقائي (Autocompletion):&lt;/b&gt; بفضل معلومات الأنواع، يمكن للمحررات الذكية (مثل VS Code) توفير اقتراحات دقيقة للإكمال التلقائي لأسماء الخصائص والدوال، مما يسرع عملية الكتابة ويقلل من الأخطاء المطبعية.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;إعادة الهيكلة الآمنة (Safer Refactoring):&lt;/b&gt; عند إعادة هيكلة الكود، يمكن لـ TypeScript تحديد جميع الأماكن التي تحتاج إلى تحديث بسبب تغيير في نوع أو اسم خاصية، مما يضمن أن التغييرات لا تكسر أجزاء أخرى من التطبيق.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;وثائق ذاتية (Self-Documenting Code):&lt;/b&gt; تحديد الأنواع يجعل الكود أكثر وضوحًا وقابلية للقراءة، حيث يمكن للمطورين الآخرين فهم الغرض من المتغيرات والخصائص دون الحاجة إلى وثائق خارجية مكثفة.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id="better-maintainability-scalability"&gt;قابلية صيانة وتوسع أفضل&lt;/h3&gt;
&lt;p&gt;مع نمو حجم التطبيق وتعقيده، تصبح قابلية الصيانة والتوسع أمرًا بالغ الأهمية. يساعد TypeScript في تحقيق ذلك من خلال:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;بنية كود واضحة:&lt;/b&gt; الأنواع الواضحة تجعل الكود أسهل في الفهم والصيانة من قبل فرق متعددة من المطورين.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تقليل الأخطاء:&lt;/b&gt; الكشف المبكر عن الأخطاء يقلل من عدد المشكلات التي تظهر في بيئة الإنتاج، مما يقلل من تكاليف الصيانة.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;دعم المشاريع الكبيرة:&lt;/b&gt; في المشاريع التي تضم مئات المكونات وآلاف الأسطر من الكود، يوفر TypeScript شبكة أمان تمنع الأخطاء الشائعة وتسهل إدارة التعقيد.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="practical-implementation"&gt;التطبيق العملي: إعداد مشروع React مع TypeScript&lt;/h2&gt;
&lt;p&gt;بدء مشروع React مع TypeScript أمر بسيط نسبيًا. يمكن استخدام أداة &lt;code&gt;create-react-app&lt;/code&gt; أو Vite لإنشاء قالب مشروع جاهز.&lt;/p&gt;

&lt;h3 id="installation"&gt;التثبيت&lt;/h3&gt;
&lt;p&gt;لإنشاء مشروع React مع TypeScript باستخدام &lt;code&gt;create-react-app&lt;/code&gt;، يمكنك استخدام الأمر التالي:&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code class='language-bash'&gt;npx create-react-app my-app --template &lt;mark class='green'&gt;typescript&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;أو باستخدام Vite، وهو أسرع وأكثر حداثة:&lt;/p&gt;
&lt;pre data-comment='Bash' data-source='terminal'&gt;&lt;code class='language-bash'&gt;npm create vite@latest my-vite-app -- --template &lt;mark class='green'&gt;react-ts&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="component-example"&gt;مثال على مكون React مع TypeScript&lt;/h3&gt;
&lt;p&gt;لنلقِ نظرة على مثال بسيط لمكون React مكتوب بـ TypeScript. سنقوم بتعريف واجهة (interface) لخصائص المكون لضمان تمرير البيانات الصحيحة.&lt;/p&gt;
&lt;pre data-comment='TypeScript JSX' data-source='src/components/Greeting.tsx'&gt;&lt;code&gt;&lt;mark class='green block'&gt;// تعريف واجهة لخصائص المكون&lt;/mark&gt;
interface GreetingProps {
  name: string;
  age?: number; &lt;mark class='block gray'&gt;// خاصية اختيارية&lt;/mark&gt;
}

&lt;mark class='green block'&gt;// تعريف المكون الوظيفي باستخدام TypeScript&lt;/mark&gt;
const Greeting: React.FC&amp;lt;GreetingProps&amp;gt; = ({ name, age }) =&gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Hello, {name}!&amp;lt;/h2&amp;gt;
      {age &amp;&amp; &amp;lt;p&amp;gt;You are {age} years old.&amp;lt;/p&amp;gt;}
    &amp;lt;/div&amp;gt;
  );
};

export default Greeting;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;في هذا المثال، قمنا بتعريف الواجهة &lt;code&gt;GreetingProps&lt;/code&gt; التي تحدد أن المكون يتوقع خاصية &lt;code&gt;name&lt;/code&gt; من نوع &lt;code&gt;string&lt;/code&gt;، وخاصية &lt;code&gt;age&lt;/code&gt; اختيارية من نوع &lt;code&gt;number&lt;/code&gt;. هذا يضمن أن أي استخدام للمكون &lt;code&gt;Greeting&lt;/code&gt; يجب أن يلتزم بهذه الأنواع.&lt;/p&gt;
&lt;pre data-comment='TypeScript JSX' data-source='src/App.tsx'&gt;&lt;code&gt;import React from 'react';
import Greeting from './components/Greeting';

function App() {
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;Greeting name="Alice" age={30} /&amp;gt;
      &amp;lt;Greeting name="Bob" /&amp;gt; &lt;mark class='green block'&gt;// العمر اختياري، لذا هذا صالح&lt;/mark&gt;
      &lt;mark class='red block'&gt;&amp;lt;Greeting name={123} /&amp;gt; // سيحدث خطأ في الترجمة: 'name' يجب أن يكون string&lt;/mark&gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;إذا حاولت تمرير قيمة غير صحيحة لخاصية &lt;code&gt;name&lt;/code&gt; (مثل رقم بدلاً من نص)، فسيقوم TypeScript بالإبلاغ عن خطأ في وقت الترجمة، مما يمنع هذا النوع من الأخطاء من الوصول إلى بيئة التشغيل.&lt;/p&gt;

&lt;div class='alert info outline'&gt;
  &lt;p&gt;&lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;استخدم &lt;b style='color:var(--linkC)'&gt;React.FC&lt;/b&gt; (اختصار لـ Function Component) لتحديد نوع المكون الوظيفي، والذي يوفر أنواعًا تلقائية لـ &lt;code&gt;children&lt;/code&gt; و &lt;code&gt;displayName&lt;/code&gt; وغيرها.&lt;/p&gt;
&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل يمكنني تحويل مشروع React موجود إلى TypeScript؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكن تحويل مشروع React موجود إلى TypeScript تدريجيًا. تبدأ العملية عادةً بإعادة تسمية ملفات &lt;code&gt;.js&lt;/code&gt; إلى &lt;code&gt;.tsx&lt;/code&gt; أو &lt;code&gt;.ts&lt;/code&gt; وتثبيت حزم TypeScript اللازمة، ثم البدء في إضافة الأنواع تدريجيًا إلى المكونات والدوال.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;ما هو الفرق الرئيسي بين TypeScript و JavaScript؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;الفرق الرئيسي هو أن TypeScript يضيف نظام الأنواع الثابتة إلى JavaScript. هذا يعني أنه يمكنك تحديد أنواع المتغيرات والدوال، مما يساعد على اكتشاف الأخطاء في وقت الترجمة ويوفر تجربة تطوير أفضل مع ميزات مثل الإكمال التلقائي وإعادة الهيكلة الآمنة. JavaScript هي لغة ديناميكية الأنواع.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
  &lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
    &lt;summary itemprop='name'&gt;هل استخدام TypeScript يبطئ عملية التطوير؟&lt;/summary&gt;
    &lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;في البداية، قد يستغرق الأمر بعض الوقت الإضافي لتعلم TypeScript وتحديد الأنواع. ومع ذلك، على المدى الطويل، يؤدي TypeScript إلى تسريع عملية التطوير بشكل كبير من خلال تقليل الأخطاء، وتحسين قابلية القراءة، وتوفير أدوات تطوير قوية، مما يوفر وقتًا ثمينًا في تصحيح الأخطاء والصيانة.&lt;/p&gt;&lt;/div&gt;
  &lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/06/react-typescript-optimal-frontend.html'&gt;React.js و TypeScript: التوافق الأمثل لتطوير الواجهة الأمامية&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صِوان AI&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>إدارة الثوابت والتحقق منها في واجهات برمجة تطبيقات Express.js باستخدام TypeScript</title><link>https://www.siwane.xyz/2026/06/typescript-express.html</link><category>مقالات AI</category><pubDate>Mon, 15 Jun 2026 10:27:58 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-4099118395098699980</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="إدارة الثوابت والتحقق منها في واجهات برمجة تطبيقات Express.js باستخدام TypeScript" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;استكشف أفضل الممارسات لتعريف قوائم الثوابت والتحقق من قيم المتغيرات مقابلها في واجهات برمجة تطبيقات Express.js المكتوبة بـ TypeScript لتعزيز الموثوقية.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; تطوير واجهات برمجة التطبيقات (APIs) باستخدام Express.js و TypeScript، يعد تعريف الثوابت وإدارتها بشكل فعال أمرًا بالغ الأهمية للحفاظ على جودة الكود، وتحسين قابلية القراءة، وتقليل الأخطاء المحتملة. يركز هذا المقال على تقديم حلول عملية لتعريف قوائم الثوابت والتحقق من أن قيمة متغير ما تقع ضمن هذه القوائم، مع التركيز على أفضل الممارسات الهندسية.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="why-define-constants-in-typescript-express-apis"&gt;لماذا تعريف الثوابت في واجهات برمجة تطبيقات TypeScript Express؟&lt;/h2&gt;
&lt;p class='pIndent'&gt;يساهم تعريف الثوابت في تحسين العديد من جوانب جودة الكود. أولاً، يزيد من &lt;b style='color:var(--linkC)'&gt;قابلية القراءة&lt;/b&gt; من خلال استبدال "الأرقام السحرية" أو السلاسل النصية المتكررة بأسماء ذات معنى. ثانيًا، يعزز &lt;b style='color:var(--linkC)'&gt;سهولة الصيانة&lt;/b&gt;؛ فإذا تغيرت قيمة ثابت، يكفي تعديله في مكان واحد فقط. أخيرًا، ومع استخدام TypeScript، توفر الثوابت &lt;b style='color:var(--linkC)'&gt;التحقق من النوع (Type Safety)&lt;/b&gt; في وقت التصريف، مما يقلل بشكل كبير من الأخطاء في وقت التشغيل.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
    &lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;
    يُعد استخدام TypeScript مع Express.js ميزة قوية، حيث يضيف طبقة من الأمان والوضوح إلى تطبيقك، خاصة عند التعامل مع البيانات المدخلة والمخرجة.
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="defining-lists-of-constants-in-typescript"&gt;تعريف قوائم الثوابت في TypeScript&lt;/h2&gt;
&lt;p class='pIndent'&gt;هناك عدة طرق لتعريف قوائم الثوابت في TypeScript، كل منها يناسب سيناريوهات مختلفة. سنستعرض أبرز هذه الطرق مع أمثلة عملية.&lt;/p&gt;

&lt;h3 id="using-enums"&gt;1. استخدام التعدادات (Enums)&lt;/h3&gt;
&lt;p class='pIndent'&gt;تُعد التعدادات طريقة ممتازة لتعريف مجموعة من القيم المتصلة. يمكن أن تكون قيمها رقمية أو نصية.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/constants/user-roles.ts'&gt;&lt;code&gt;
&amp;lt;mark class='block' data-before='تعريف تعداد للأدوار:'&amp;gt;export enum UserRole {
  ADMIN = &amp;quot;admin&amp;quot;,
  EDITOR = &amp;quot;editor&amp;quot;,
  VIEWER = &amp;quot;viewer&amp;quot;,
}&amp;lt;/mark&amp;gt;

&amp;lt;mark class='block' data-before='استخدام التعداد:'&amp;gt;const currentUserRole: UserRole = UserRole.ADMIN;
console.log(currentUserRole); // &amp;quot;admin&amp;quot;&amp;lt;/mark&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;تُنشئ التعدادات كائنات JavaScript في وقت التشغيل، مما يتيح لك الوصول إلى القيم والأسماء بسهولة.&lt;/p&gt;

&lt;h3 id="using-union-types-with-literal-types"&gt;2. استخدام أنواع الاتحاد (Union Types) مع الأنواع الحرفية (Literal Types)&lt;/h3&gt;
&lt;p class='pIndent'&gt;هذه الطريقة توفر تعريفًا خفيف الوزن لمجموعة محددة من القيم، وتُعد مفيدة للتحقق من النوع في وقت التصريف.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/types/common.ts'&gt;&lt;code&gt;
&amp;lt;mark class='block' data-before='تعريف نوع اتحاد للأدوار:'&amp;gt;export type AllowedUserRole = &amp;quot;admin&amp;quot; | &amp;quot;editor&amp;quot; | &amp;quot;viewer&amp;quot;;
&amp;lt;/mark&amp;gt;
&amp;lt;mark class='block' data-before='استخدام نوع الاتحاد:'&amp;gt;const userPermission: AllowedUserRole = &amp;quot;editor&amp;quot;;
// const invalidPermission: AllowedUserRole = &amp;quot;guest&amp;quot;; // خطأ في التصريف&amp;lt;/mark&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="using-const-arrays-or-objects"&gt;3. استخدام مصفوفات أو كائنات `const` مع `as const`&lt;/h3&gt;
&lt;p class='pIndent'&gt;عندما تحتاج إلى قائمة من الثوابت التي يمكن تكرارها أو استخدامها كمرجع في وقت التشغيل، فإن استخدام مصفوفات أو كائنات `const` مع &lt;b style='color:var(--linkC)'&gt;`as const`&lt;/b&gt; هو الخيار الأمثل. يخبر `as const` TypeScript بمعاملة القيم كأنواع حرفية (literal types)، مما يجعل المصفوفة أو الكائن "للقراءة فقط" (read-only) ويحسن التحقق من النوع.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/constants/app-settings.ts'&gt;&lt;code&gt;
&amp;lt;mark class='block' data-before='تعريف مصفوفة ثوابت للحالات:'&amp;gt;export const VALID_ORDER_STATUSES = [
  &amp;quot;pending&amp;quot;,
  &amp;quot;processing&amp;quot;,
  &amp;quot;shipped&amp;quot;,
  &amp;quot;delivered&amp;quot;,
  &amp;quot;cancelled&amp;quot;,
] as const;
&amp;lt;/mark&amp;gt;
&amp;lt;mark class='block' data-before='تعريف كائن ثوابت لنقاط النهاية:'&amp;gt;export const API_ENDPOINTS = {
  USERS: &amp;quot;/api/users&amp;quot;,
  PRODUCTS: &amp;quot;/api/products&amp;quot;,
  ORDERS: &amp;quot;/api/orders&amp;quot;,
} as const;
&amp;lt;/mark&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class='alert warning'&gt;
    &lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;
    استخدام `as const` يحول المصفوفة أو الكائن إلى نوع للقراءة فقط، مما يمنع التعديل غير المقصود على القيم في وقت التشغيل.
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="checking-if-a-variable-value-is-in-the-list"&gt;التحقق مما إذا كانت قيمة متغير موجودة في القائمة&lt;/h2&gt;
&lt;p class='pIndent'&gt;بعد تعريف قوائم الثوابت، الخطوة التالية هي التحقق مما إذا كانت قيمة متغير معين تقع ضمن هذه القوائم. هذا أمر شائع في التحقق من صحة المدخلات (validation) في واجهات برمجة التطبيقات.&lt;/p&gt;

&lt;h3 id="checking-with-enums"&gt;1. التحقق باستخدام التعدادات (Enums)&lt;/h3&gt;
&lt;p class='pIndent'&gt;يمكنك استخدام &lt;b style='color:var(--linkC)'&gt;`Object.values()`&lt;/b&gt; للحصول على مصفوفة من قيم التعداد ثم استخدام &lt;b style='color:var(--linkC)'&gt;`.includes()`&lt;/b&gt; للتحقق.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/middleware/auth.ts'&gt;&lt;code&gt;
import { Request, Response, NextFunction } from 'express';
import { UserRole } from '../constants/user-roles'; // افتراض أنك عرفت UserRole enum

&amp;lt;mark class='block green' data-before='+'&amp;gt;export const checkUserRole = (allowedRoles: UserRole[]) =&amp;gt; {
  return (req: Request, res: Response, next: NextFunction) =&amp;gt; {
    const userRole = req.headers['x-user-role'] as string; // افتراض أن الدور يأتي من الهيدر

    if (!userRole || !Object.values(UserRole).includes(userRole as UserRole)) {
      return res.status(403).send('Invalid or missing user role.');
    }

    if (!allowedRoles.includes(userRole as UserRole)) {
      return res.status(403).send('Access denied.');
    }

    next();
  };
};&amp;lt;/mark&amp;gt;

&amp;lt;mark class='block' data-before='استخدام الوسيط في Express:'&amp;gt;// app.get('/admin-dashboard', checkUserRole([UserRole.ADMIN]), (req, res) =&amp;gt; {
//   res.send('Welcome to the admin dashboard!');
// });&amp;lt;/mark&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="checking-with-const-arrays"&gt;2. التحقق باستخدام مصفوفات `const`&lt;/h3&gt;
&lt;p class='pIndent'&gt;تُعد هذه الطريقة الأكثر مباشرة وفعالية للتحقق من وجود قيمة في قائمة محددة من الثوابت، مع الحفاظ على التحقق من النوع بفضل `as const`.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/utils/validation.ts'&gt;&lt;code&gt;
import { VALID_ORDER_STATUSES } from '../constants/app-settings';

&amp;lt;mark class='block green' data-before='+'&amp;gt;export function isValidOrderStatus(status: string): status is typeof VALID_ORDER_STATUSES[number] {
  return (VALID_ORDER_STATUSES as readonly string[]).includes(status);
}&amp;lt;/mark&amp;gt;

&amp;lt;mark class='block' data-before='مثال على الاستخدام في معالج مسار Express:'&amp;gt;import { Request, Response } from 'express';

export const updateOrderStatus = (req: Request, res: Response) =&amp;gt; {
  const { id } = req.params;
  const { newStatus } = req.body;

  if (!isValidOrderStatus(newStatus)) {
    return res.status(400).send(`Invalid status: ${newStatus}. Allowed statuses are: ${VALID_ORDER_STATUSES.join(', ')}`);
  }

  // منطق تحديث الحالة في قاعدة البيانات
  res.status(200).send(`Order ${id} updated to ${newStatus}`);
};&amp;lt;/mark&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class='alert success'&gt;
    &lt;b&gt;حل!&lt;/b&gt;&lt;br/&gt;
    باستخدام `status is typeof VALID_ORDER_STATUSES[number]`، فإننا نُعلم TypeScript أن المتغير `status`، بعد اجتياز التحقق، سيكون من أحد الأنواع الحرفية المحددة في المصفوفة، مما يوفر تحكمًا قويًا بالنوع.
&lt;/div&gt;

&lt;p class='pIndent'&gt;يُعد تعريف الثوابت والتحقق منها جزءًا لا يتجزأ من بناء واجهات برمجة تطبيقات قوية وموثوقة باستخدام Express.js و TypeScript. من خلال تطبيق هذه الأساليب، يمكنك تعزيز قابلية صيانة الكود، وتقليل الأخطاء، وتحسين تجربة المطور بشكل عام.&lt;/p&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/06/typescript-express.html'&gt;إدارة الثوابت والتحقق منها في واجهات برمجة تطبيقات Express.js باستخدام TypeScript&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>تبديد الغموض: إعلانات دوال ومكونات React TypeScript</title><link>https://www.siwane.xyz/2026/06/react-typescript.html</link><category>مقالات AI</category><pubDate>Mon, 1 Jun 2026 10:27:47 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-7212970632173215079</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="تبديد الغموض: إعلانات دوال ومكونات React TypeScript" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;مقالة تقنية تركز على توضيح الفروقات الجوهرية وأفضل الممارسات لإعلان الدوال ومكونات React الوظيفية باستخدام TypeScript.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الواجهات الأمامية الحديث، أصبحت React.js و TypeScript ثنائيًا لا غنى عنه لإنشاء تطبيقات قوية وقابلة للصيانة. ومع ذلك، يواجه العديد من المطورين، خاصة الجدد منهم، بعض الالتباس عند محاولة فهم كيفية إعلان الدوال العادية ومكونات React الوظيفية (Function Components) باستخدام TypeScript. يهدف هذا المقال إلى تبديد هذا الغموض من خلال تقديم شروحات عملية وأمثلة واضحة.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="understanding-the-core-confusion"&gt;فهم الالتباس الأساسي&lt;/h2&gt;
&lt;p class='pIndent'&gt;ينبع الالتباس غالبًا من حقيقة أن كلًا من الدوال العادية ومكونات React الوظيفية هي في جوهرها دوال JavaScript. ومع ذلك، فإن سياقهما واستخدامهما في تطبيق React يختلفان بشكل كبير. تتوقع React أن تعيد المكونات الوظيفية عناصر JSX، بينما يمكن للدوال العادية أن تعيد أي نوع من البيانات أو لا تعيد شيئًا على الإطلاق (&lt;code&gt;void&lt;/code&gt;). يضيف TypeScript طبقة من التحقق الثابت للنوع (Static Type Checking) التي تتطلب تحديد أنواع المدخلات والمخرجات بدقة، مما يجعل التمييز بينهما أكثر أهمية.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="declaring-regular-functions-in-typescript"&gt;إعلان الدوال العادية في TypeScript&lt;/h2&gt;
&lt;p class='pIndent'&gt;عند إعلان دالة JavaScript عادية في TypeScript، يجب تحديد أنواع المعاملات (Parameters) ونوع القيمة المرتجعة (Return Type) بشكل صريح. هذا يضمن أن الدالة تعمل بالبيانات المتوقعة وتعيد النوع الصحيح، مما يحسن من موثوقية الكود.&lt;/p&gt;

&lt;h3 id="named-functions"&gt;الدوال المسماة (Named Functions)&lt;/h3&gt;
&lt;p class='pIndent'&gt;هذا هو الشكل التقليدي لإعلان الدالة، حيث يتم تحديد اسمها وأنواعها بوضوح.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/utils/math.ts'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على دالة جمع مسماة:'&gt;function sum(a: number, b: number): number {
  return a + b;
}&lt;/mark&gt;

&lt;mark class='block blue' data-after='هنا، &amp;lt;mark&amp;gt;a&amp;lt;/mark&amp;gt; و &amp;lt;mark&amp;gt;b&amp;lt;/mark&amp;gt; من النوع &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;، والقيمة المرتجعة أيضًا &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;.'&gt;function greet(name: string): void {
  console.log(`Hello, ${name}!`);
}&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="arrow-functions"&gt;دوال السهم (Arrow Functions)&lt;/h3&gt;
&lt;p class='pIndent'&gt;تُستخدم دوال السهم بشكل شائع في JavaScript الحديثة، ويمكن تطبيق نفس مبادئ تحديد الأنواع عليها.&lt;/p&gt;
&lt;pre data-comment='.ts' data-source='src/utils/math.ts'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على دالة ضرب بسهم:'&gt;const multiply = (a: number, b: number): number =&gt; a * b;&lt;/mark&gt;

&lt;mark class='block blue' data-after='هنا، &amp;lt;mark&amp;gt;message&amp;lt;/mark&amp;gt; من النوع &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;، ولا توجد قيمة مرتجعة (أي &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;).'&gt;const logMessage = (message: string): void =&gt; {
  console.log(message);
};&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class='alert info'&gt;
  &lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;
  تذكر أن هذه الدوال لا ترتبط بـ React بشكل مباشر؛ إنها مجرد دوال مساعدة يمكن استخدامها في أي جزء من تطبيقك.
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="declaring-react-function-components-in-typescript"&gt;إعلان مكونات React الوظيفية في TypeScript&lt;/h2&gt;
&lt;p class='pIndent'&gt;تختلف مكونات React الوظيفية عن الدوال العادية في أنها تتلقى &lt;code&gt;props&lt;/code&gt; كمعامل وحيد وتعيد عناصر JSX. هناك طريقتان رئيسيتان لتحديد أنواع هذه المكونات في TypeScript.&lt;/p&gt;

&lt;h3 id="using-react-fc"&gt;استخدام &lt;code&gt;React.FC&lt;/code&gt; (أو &lt;code&gt;FC&lt;/code&gt;)&lt;/h3&gt;
&lt;p class='pIndent'&gt;كان &lt;code&gt;React.FC&lt;/code&gt; (اختصار لـ Function Component) هو النمط الموصى به لتحديد أنواع مكونات React الوظيفية. يوفر هذا النوع بعض الميزات مثل تضمين نوع &lt;code&gt;children&lt;/code&gt; بشكل ضمني.&lt;/p&gt;
&lt;pre data-comment='.tsx' data-source='src/components/Greeting.tsx'&gt;&lt;code&gt;import React from 'react';

&lt;mark class='block' data-before='تعريف واجهة الخصائص (Props Interface):'&gt;interface GreetingProps {
  name: string;
  age?: number; // خاصية اختيارية
}&lt;/mark&gt;

&lt;mark class='block blue' data-after='هنا، &amp;lt;code&amp;gt;Greeting&amp;lt;/code&amp;gt; يتم تعريفها كمكون وظيفي لـ React يقبل خصائص من النوع &amp;lt;code&amp;gt;GreetingProps&amp;lt;/code&amp;gt;.'&gt;const Greeting: React.FC&amp;lt;GreetingProps&amp;gt; = ({ name, age }) =&gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Hello, {name}!&amp;lt;/h2&amp;gt;
      {age &amp;&amp; &amp;lt;p&amp;gt;You are {age} years old.&amp;lt;/p&amp;gt;}
    &amp;lt;/div&amp;gt;
  );
};&lt;/mark&gt;

export default Greeting;&lt;/code&gt;&lt;/pre&gt;
&lt;div class='alert warning outline'&gt;
  &lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;
  على الرغم من شيوع &lt;code&gt;React.FC&lt;/code&gt;، إلا أنه لم يعد النمط الموصى به في العديد من المشاريع الحديثة. أحد أسباب ذلك هو أنه يضيف &lt;code&gt;children&lt;/code&gt; كخاصية اختيارية بشكل ضمني، مما قد يؤدي إلى سلوك غير متوقع إذا لم تكن تتوقع &lt;code&gt;children&lt;/code&gt; دائمًا.
&lt;/div&gt;

&lt;h3 id="direct-typing-pattern-recommended"&gt;النمط المباشر (الموصى به)&lt;/h3&gt;
&lt;p class='pIndent'&gt;يُعد تحديد أنواع الخصائص مباشرة في معامل الدالة هو النمط المفضل حاليًا. يمنحك هذا تحكمًا أكبر في أنواع الخصائص، بما في ذلك &lt;code&gt;children&lt;/code&gt;.&lt;/p&gt;
&lt;pre data-comment='.tsx' data-source='src/components/Button.tsx'&gt;&lt;code&gt;import React from 'react';

&lt;mark class='block' data-before='تعريف واجهة الخصائص:'&gt;interface ButtonProps {
  onClick: () =&gt; void;
  label: string;
  children?: React.ReactNode; // تحديد &amp;lt;code&amp;gt;children&amp;lt;/code&amp;gt; بشكل صريح
}&lt;/mark&gt;

&lt;mark class='block blue' data-after='هنا، يتم تحديد أنواع الخصائص مباشرة في معامل الدالة.'&gt;const Button = ({ onClick, label, children }: ButtonProps) =&gt; {
  return (
    &amp;lt;button onClick={onClick}&amp;gt;
      {label}
      {children}
    &amp;lt;/button&amp;gt;
  );
};&lt;/mark&gt;

export default Button;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;إذا كنت تتوقع دائمًا وجود &lt;code&gt;children&lt;/code&gt;، يمكنك استخدام &lt;code&gt;React.PropsWithChildren&lt;/code&gt; لتسهيل الأمر:&lt;/p&gt;
&lt;pre data-comment='.tsx' data-source='src/components/Card.tsx'&gt;&lt;code&gt;import React from 'react';

&lt;mark class='block' data-before='تعريف واجهة الخصائص (بدون &amp;lt;code&amp;gt;children&amp;lt;/code&amp;gt;):'&gt;interface CardProps {
  title: string;
}&lt;/mark&gt;

&lt;mark class='block blue' data-after='&amp;lt;code&amp;gt;React.PropsWithChildren&amp;lt;/code&amp;gt; يضيف &amp;lt;code&amp;gt;children?: React.ReactNode&amp;lt;/code&amp;gt; تلقائيًا.'&gt;const Card = ({ title, children }: React.PropsWithChildren&amp;lt;CardProps&amp;gt;) =&gt; {
  return (
    &amp;lt;div style={{ border: '1px solid gray', padding: '10px' }}&amp;gt;
      &amp;lt;h3&amp;gt;{title}&amp;lt;/h3&amp;gt;
      {children}
    &amp;lt;/div&amp;gt;
  );
};&lt;/mark&gt;

export default Card;&lt;/code&gt;&lt;/pre&gt;

&lt;hr&gt;

&lt;h2 id="best-practices-and-tips"&gt;أفضل الممارسات والنصائح&lt;/h2&gt;
&lt;ol class="steps"&gt;
  &lt;li&gt;&lt;b&gt;كن صريحًا دائمًا:&lt;/b&gt; حدد أنواع المعاملات والقيم المرتجعة بوضوح لكل من الدوال العادية والمكونات.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;تفضيل النمط المباشر للمكونات:&lt;/b&gt; استخدم تحديد أنواع الخصائص مباشرة في معامل الدالة لمكونات React الوظيفية. هذا يمنحك تحكمًا أفضل ووضوحًا أكبر.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;استخدم &lt;code&gt;React.PropsWithChildren&lt;/code&gt; عند الحاجة:&lt;/b&gt; إذا كان مكونك يتوقع &lt;code&gt;children&lt;/code&gt; دائمًا، فإن &lt;code&gt;React.PropsWithChildren&lt;/code&gt; طريقة نظيفة لإضافة هذا النوع دون كتابته يدويًا.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;فهم &lt;code&gt;React.ReactNode&lt;/code&gt;:&lt;/b&gt; استخدم &lt;code&gt;React.ReactNode&lt;/code&gt; لخاصية &lt;code&gt;children&lt;/code&gt; عندما يمكن أن تكون أي شيء يمكن لـ React عرضه (سلاسل، أرقام، عناصر JSX، مصفوفات من هذه الأنواع، إلخ).&lt;/li&gt;
&lt;/ol&gt;
&lt;div class='alert success'&gt;
  &lt;b&gt;حل!&lt;/b&gt;&lt;br/&gt;
  باتباع هذه الإرشادات، يمكنك كتابة كود React و TypeScript أكثر وضوحًا وقابلية للصيانة، مما يقلل من الالتباس ويحسن تجربة التطوير.
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/06/react-typescript.html'&gt;تبديد الغموض: إعلانات دوال ومكونات React TypeScript&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>تصدير Excel في Node.js: إضافة روابط تشعبية لألسنة العمل</title><link>https://www.siwane.xyz/2026/05/nodejs.html</link><category>مقالات AI</category><pubDate>Mon, 25 May 2026 10:27:47 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-1852105296910125204</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="تصدير Excel في Node.js: إضافة روابط تشعبية لألسنة العمل" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;دليل عملي لتضمين روابط تشعبية داخل ملفات Excel المصدرة باستخدام Node.js، مع التركيز على توجيه المستخدمين إلى ألسنة عمل محددة.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; سياق تطوير تطبيقات الويب التي تتطلب تصدير البيانات إلى ملفات Excel، يواجه المطورون أحيانًا الحاجة إلى إنشاء تجربة مستخدم أكثر تفاعلية. إحدى هذه المتطلبات هي القدرة على إضافة روابط تشعبية (hyperlinks) توجه المستخدم مباشرة إلى ألسنة عمل (sheets) محددة داخل نفس المصنف (workbook)، مما يسهل التنقل ويحسن من قابلية استخدام التقرير المصدر. هذا المقال يقدم حلولاً هندسية عملية لتحقيق ذلك باستخدام Node.js.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="understanding-internal-hyperlinks-in-excel"&gt;فهم الروابط التشعبية الداخلية في Excel&lt;/h2&gt;
&lt;p class='pIndent'&gt;قبل الغوص في التفاصيل التقنية، من المهم فهم كيفية عمل الروابط التشعبية الداخلية في Excel. عندما تنشئ رابطًا تشعبيًا داخل Excel يوجه إلى ورقة عمل أخرى، فإنك في الواقع تشير إلى اسم الورقة متبوعًا بعلامة التعجب واسم الخلية (على سبيل المثال، &lt;b style='color:var(--linkC)'&gt;#SheetName!A1&lt;/b&gt;). هذه الصيغة هي المفتاح الذي سنستخدمه لبرمجة هذه الروابط في Node.js.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;
تعتبر مكتبة &lt;a class='extL sec' href='https://www.npmjs.com/package/exceljs' rel='nofollow noreferrer noopener' target='_blank'&gt;ExcelJS&lt;/a&gt; خيارًا ممتازًا في Node.js للتعامل مع ملفات Excel (.xlsx)، حيث توفر واجهة برمجية قوية لإنشاء، قراءة، وتعديل المصنفات، بما في ذلك دعم الروابط التشعبية.
&lt;/div&gt;
&lt;h3 id="choosing-the-right-tool"&gt;اختيار الأداة المناسبة&lt;/h3&gt;
&lt;p class='pIndent'&gt;لتحقيق هذا الهدف في Node.js، سنعتمد على مكتبة &lt;b style='color:var(--linkC)'&gt;ExcelJS&lt;/b&gt; نظرًا لمرونتها وقدرتها على التعامل مع تفاصيل بنية ملفات Excel. توفر هذه المكتبة وظائف مباشرة لإضافة الروابط التشعبية إلى الخلايا، مما يجعلها مثالية لمهمتنا.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="implementing-hyperlinks-to-specific-tabs-with-exceljs"&gt;تطبيق الروابط التشعبية لألسنة العمل باستخدام ExcelJS&lt;/h2&gt;
&lt;p class='pIndent'&gt;الخطوات التالية توضح كيفية إنشاء مصنف Excel، إضافة ألسنة عمل متعددة، ثم إضافة رابط تشعبي في ورقة عمل رئيسية يوجه إلى ورقة عمل أخرى.&lt;/p&gt;
&lt;h3 id="initial-setup-and-workbook-creation"&gt;الإعداد الأولي وإنشاء المصنف&lt;/h3&gt;
&lt;p class='pIndent'&gt;أولاً، قم بتثبيت &lt;b style='color:var(--linkC)'&gt;ExcelJS&lt;/b&gt; إذا لم تكن قد فعلت ذلك بالفعل:&lt;/p&gt;
&lt;pre data-comment='.bash' data-source='terminal'&gt;&lt;code class='language-bash'&gt;&lt;mark class='green' data-before='$'&gt;npm install exceljs&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;بعد التثبيت، يمكنك البدء بإنشاء مصنف جديد وإضافة ألسنة العمل.&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/excel-exporter.js'&gt;&lt;code&gt;const ExcelJS = require('exceljs');

async function createExcelWithTabLinks() {
    const workbook = new ExcelJS.Workbook();
    workbook.creator = 'Your Name';
    workbook.lastModifiedBy = 'Your Name';
    workbook.created = new Date();
    workbook.modified = new Date();

    // إضافة ألسنة العمل
    const summarySheet = workbook.addWorksheet('الملخص');
    const detailsSheet1 = workbook.addWorksheet('تفاصيل_1');
    const detailsSheet2 = workbook.addWorksheet('تفاصيل_2');

    // إعداد بعض البيانات في ألسنة العمل التفصيلية
    detailsSheet1.getCell('A1').value = 'هذه بيانات تفاصيل 1';
    detailsSheet2.getCell('A1').value = 'هذه بيانات تفاصيل 2';

    // ... (يمكنك إضافة المزيد من البيانات هنا) ...

    &lt;mark class='block blue' data-after='الخطوة التالية هي إضافة الروابط التشعبية في ورقة الملخص.'&gt;return { workbook, summarySheet, detailsSheet1, detailsSheet2 };&lt;/mark&gt;
}&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="adding-hyperlinks-to-the-summary-sheet"&gt;إضافة الروابط التشعبية إلى ورقة الملخص&lt;/h3&gt;
&lt;p class='pIndent'&gt;الآن، سنقوم بإضافة الروابط التشعبية إلى ورقة "الملخص" التي ستوجه المستخدم إلى ألسنة العمل التفصيلية.&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/excel-exporter.js'&gt;&lt;code&gt;async function addHyperlinks(workbook, summarySheet) {
    // الرابط التشعبي لورقة 'تفاصيل_1'
    summarySheet.getCell('A1').value = {
        text: 'انتقل إلى تفاصيل 1',
        hyperlink: &lt;mark class='red'&gt;'#تفاصيل_1!A1'&lt;/mark&gt; // الصيغة الأساسية للرابط الداخلي
    };
    summarySheet.getCell('A1').font = { color: { argb: 'FF0000FF' }, underline: true };

    // الرابط التشعبي لورقة 'تفاصيل_2'
    summarySheet.getCell('A2').value = {
        text: 'انتقل إلى تفاصيل 2',
        hyperlink: &lt;mark class='red'&gt;'#تفاصيل_2!A1'&lt;/mark&gt;
    };
    summarySheet.getCell('A2').font = { color: { argb: 'FF0000FF' }, underline: true };

    // ... (يمكنك إضافة المزيد من الروابط هنا) ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;لاحظ كيف يتم تحديد خاصية &lt;b style='color:var(--linkC)'&gt;hyperlink&lt;/b&gt; في كائن قيمة الخلية. القيمة &lt;mark class='red'&gt;'#تفاصيل_1!A1'&lt;/mark&gt; هي التي تخبر Excel بالانتقال إلى الخلية A1 في ورقة العمل المسماة "تفاصيل_1".&lt;/p&gt;

&lt;h3 id="exporting-the-excel-file"&gt;تصدير ملف Excel&lt;/h3&gt;
&lt;p class='pIndent'&gt;أخيرًا، قم بتصدير المصنف إلى ملف.&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/excel-exporter.js'&gt;&lt;code&gt;const path = require('path');

async function exportExcel() {
    const { workbook, summarySheet } = await createExcelWithTabLinks();
    await addHyperlinks(workbook, summarySheet);

    const filePath = path.join(__dirname, 'تقرير_مع_روابط.xlsx');
    await workbook.xlsx.writeFile(filePath);
    console.log(`تم إنشاء ملف Excel بنجاح في: ${filePath}`);
}

exportExcel().catch(error =&gt; {
    console.error('حدث خطأ أثناء إنشاء ملف Excel:', error);
});&lt;/code&gt;&lt;/pre&gt;
&lt;div class='alert warning'&gt;
&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;
تأكد من أن أسماء ألسنة العمل في خاصية &lt;b style='color:var(--linkC)'&gt;hyperlink&lt;/b&gt; تتطابق تمامًا مع الأسماء الفعلية لألسنة العمل التي تم إنشاؤها. أي اختلاف سيؤدي إلى رابط غير صالح.
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="best-practices-and-considerations"&gt;أفضل الممارسات والاعتبارات&lt;/h2&gt;
&lt;p class='pIndent'&gt;لضمان تجربة تصدير Excel فعالة وموثوقة، يجب مراعاة بعض أفضل الممارسات:&lt;/p&gt;
&lt;ol class="steps"&gt;
&lt;li&gt;&lt;b&gt;التعامل مع أسماء الأوراق:&lt;/b&gt; إذا كانت أسماء ألسنة العمل تحتوي على مسافات أو أحرف خاصة، فإن Excel يتعامل معها تلقائيًا بوضعها بين علامات اقتباس مفردة (على سبيل المثال، &lt;b style='color:var(--linkC)'&gt;#'My Sheet'!A1&lt;/b&gt;). &lt;b style='color:var(--linkC)'&gt;ExcelJS&lt;/b&gt; يتعامل مع هذا بشكل جيد، ولكن من الجيد أن تكون على دراية به.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;تجربة المستخدم:&lt;/b&gt; اجعل نص الرابط واضحًا ووصفيًا. يمكن أيضًا استخدام تنسيق الخط (اللون الأزرق والتسطير) لتمييز الروابط، كما هو موضح في الأمثلة.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;الأداء:&lt;/b&gt; بالنسبة لملفات Excel الكبيرة جدًا أو التي تحتوي على عدد كبير من الروابط، قد تحتاج إلى تحسين الأداء من خلال معالجة الدفق (streaming) أو تقسيم العمليات.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;التحقق من الأخطاء:&lt;/b&gt; أضف معالجة الأخطاء المناسبة عند كتابة الملف لضمان التعامل السليم مع أي مشكلات قد تنشأ أثناء عملية التصدير.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote class="s1"&gt;&lt;p&gt;إن القدرة على توجيه المستخدمين بسلاسة داخل المستندات الكبيرة ليست مجرد ميزة، بل هي ضرورة لتحسين كفاءة استهلاك البيانات.&lt;/p&gt;&lt;span&gt;مطور برمجيات&lt;/span&gt;&lt;/blockquote&gt;

&lt;div class='alert success'&gt;
&lt;b&gt;حل!&lt;/b&gt;&lt;br/&gt;
باستخدام &lt;b style='color:var(--linkC)'&gt;ExcelJS&lt;/b&gt;، يمكنك بسهولة إنشاء مصنفات Excel ديناميكية تحتوي على روابط تشعبية داخلية، مما يحول تقاريرك الثابتة إلى أدوات تفاعلية.
&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;هل يمكنني إضافة روابط تشعبية لملفات خارجية بدلاً من ألسنة العمل الداخلية؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكن لـ ExcelJS دعم الروابط التشعبية لملفات خارجية أو عناوين URL على الويب. بدلاً من استخدام صيغة &lt;b style='color:var(--linkC)'&gt;#SheetName!A1&lt;/b&gt;، يمكنك ببساطة توفير عنوان URL الكامل أو مسار الملف في خاصية &lt;b style='color:var(--linkC)'&gt;hyperlink&lt;/b&gt;، مثل &lt;b style='color:var(--linkC)'&gt;'https://www.example.com'&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;'file:///C:/path/to/file.xlsx'&lt;/b&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;ماذا لو كان اسم ورقة العمل يحتوي على مسافات أو أحرف خاصة؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;في Excel، يتم تضمين أسماء ألسنة العمل التي تحتوي على مسافات أو أحرف خاصة بعلامات اقتباس مفردة في الروابط التشعبية (على سبيل المثال، &lt;b style='color:var(--linkC)'&gt;#'My Data Sheet'!A1&lt;/b&gt;). يتعامل ExcelJS مع هذا بشكل تلقائي عند تحديد اسم الورقة بشكل صحيح في خاصية &lt;b style='color:var(--linkC)'&gt;hyperlink&lt;/b&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/05/nodejs.html'&gt;تصدير Excel في Node.js: إضافة روابط تشعبية لألسنة العمل&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>Cloudflare وحظر طلبات الـ API المباشرة: حلول هندسية</title><link>https://www.siwane.xyz/2026/05/cloudflare.html</link><category>مقالات AI</category><pubDate>Mon, 18 May 2026 10:27:57 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-5556052783453474382</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="Cloudflare وحظر طلبات الـ API المباشرة: حلول هندسية" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;Cloudflare تحظر طلبات الـ API المباشرة بينما لا يفعل Google Chrome. استكشف آليات الحظر والحلول الهندسية الفعالة لتجاوز هذه التحديات التقنية.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; هذا المقال، نستعرض ظاهرة حظر Cloudflare لطلبات واجهة برمجة التطبيقات (API) المباشرة التي تُرسل من خلال أدوات برمجية مثل `curl` أو مكتبات `requests` في Python، بينما لا يتم حظر نفس الطلبات عند إجرائها عبر متصفحات الويب مثل Google Chrome. سنقدم شروحات هندسية عملية وحلولًا دقيقة لهذه المشكلة الشائعة.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="understanding-cloudflare-blocking-mechanisms"&gt;فهم آليات حظر Cloudflare&lt;/h2&gt;
&lt;p class='pIndent'&gt;تستخدم Cloudflare مجموعة معقدة من الآليات للكشف عن الروبوتات والتهديدات المحتملة. المتصفحات الحديثة مثل Chrome تتصرف بطريقة "بشرية" متوقعة، بينما الطلبات المباشرة من الأدوات البرمجية غالبًا ما تفتقر إلى هذه الخصائص، مما يثير شكوك أنظمة Cloudflare الأمنية.&lt;/p&gt;

&lt;h3 id="browser-fingerprinting-and-request-headers"&gt;بصمات المتصفح ورؤوس الطلبات&lt;/h3&gt;
&lt;p class='pIndent'&gt;Cloudflare تفحص بدقة رؤوس HTTP المرسلة مع كل طلب. المتصفحات ترسل مجموعة غنية من الرؤوس، مثل &lt;b style='color:var(--linkC)'&gt;User-Agent&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Accept&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Accept-Language&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Accept-Encoding&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Referer&lt;/b&gt;، و &lt;b style='color:var(--linkC)'&gt;Origin&lt;/b&gt;. بالإضافة إلى ذلك، يتم تحليل ترتيب هذه الرؤوس وقيمها المحددة. الطلبات المباشرة من السكربتات غالبًا ما تكون مبسطة، أو تستخدم قيمًا افتراضية، أو تفتقر إلى التناسق الذي تتوقعه Cloudflare من متصفح حقيقي.&lt;/p&gt;

&lt;h3 id="javascript-challenges-and-cookies"&gt;تحديات JavaScript وملفات تعريف الارتباط&lt;/h3&gt;
&lt;p class='pIndent'&gt;العديد من آليات Cloudflare الأمنية تعتمد على تنفيذ JavaScript في المتصفح لجمع معلومات إضافية حول العميل أو لحل تحديات CAPTCHA. الطلبات المباشرة لا تنفذ JavaScript ولا تتعامل مع ملفات تعريف الارتباط (Cookies) التي قد تكون ضرورية للمصادقة أو لتجاوز التحقق الأولي من Cloudflare.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="diagnosing-the-blocking-cause"&gt;تشخيص سبب الحظر&lt;/h2&gt;
&lt;p class='pIndent'&gt;تحديد السبب الدقيق للحظر هو الخطوة الأولى نحو تطبيق الحل الصحيح. يتطلب ذلك مقارنة دقيقة بين سلوك المتصفح وسلوك السكربت.&lt;/p&gt;

&lt;h3 id="analyzing-http-headers"&gt;تحليل رؤوس HTTP&lt;/h3&gt;
&lt;p class='pIndent'&gt;قارن رؤوس الطلب بين طلب ناجح من Chrome وطلب فاشل من الـ API. استخدم أدوات المطور (Developer Tools) في Chrome (علامة تبويب Network) أو أدوات اعتراض حركة المرور مثل &lt;a class='extL' href='https://www.wireshark.org/' rel='nofollow noreferrer noopener' target='_blank'&gt;Wireshark&lt;/a&gt;. ابحث عن الاختلافات في الرؤوس المذكورة أعلاه. غالبًا ما يكون &lt;b style='color:var(--linkC)'&gt;User-Agent&lt;/b&gt; هو السبب الأكثر شيوعًا، يليه &lt;b style='color:var(--linkC)'&gt;Accept&lt;/b&gt; ورؤوس أخرى.&lt;/p&gt;
&lt;pre data-comment='.sh' data-source='curl-example.sh'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على طلب curl مع رؤوس متصفح:' &gt;curl -v \
     -H &amp;quot;User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36&amp;quot; \
     -H &amp;quot;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9&amp;quot; \
     -H &amp;quot;Accept-Language: en-US,en;q=0.9&amp;quot; \
     -H &amp;quot;Accept-Encoding: gzip, deflate, br&amp;quot; \
     -H &amp;quot;Referer: https://example.com/&amp;quot; \
     -H &amp;quot;Origin: https://example.com&amp;quot; \
     &amp;quot;https://api.example.com/data&amp;quot;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="inspecting-browser-behavior"&gt;فحص سلوك المتصفح&lt;/h3&gt;
&lt;p class='pIndent'&gt;راقب تدفق الشبكة في Chrome Developer Tools. هل هناك عمليات إعادة توجيه (redirects) قبل الوصول إلى الـ API الفعلي؟ هل يتم تعيين ملفات تعريف ارتباط جديدة؟ هل يتم تنفيذ JavaScript معقد قبل إرسال طلب الـ API؟ قد تشير هذه السلوكيات إلى تحديات أمنية تقوم Cloudflare بفرضها.&lt;/p&gt;

&lt;h3 id="cloudflare-logs"&gt;سجلات Cloudflare&lt;/h3&gt;
&lt;p class='pIndent'&gt;إذا كان لديك وصول إلى لوحة تحكم Cloudflare الخاصة بالموقع المستهدف، تحقق من سجلات &lt;b style='color:var(--linkC)'&gt;Firewall Events&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;Analytics&lt;/b&gt;. قد توضح هذه السجلات قاعدة الحظر المحددة التي تم تفعيلها (مثل &lt;b style='color:var(--linkC)'&gt;Bot Fight Mode&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Rate Limiting&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;Managed Rules&lt;/b&gt;)، مما يوفر معلومات قيمة حول سبب الحظر.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="practical-engineering-solutions"&gt;حلول هندسية عملية&lt;/h2&gt;
&lt;p class='pIndent'&gt;تتطلب معالجة حظر Cloudflare نهجًا متعدد الأوجه، يعتمد على مستوى التحكم الذي لديك في إعدادات Cloudflare والتعقيد المطلوب.&lt;/p&gt;

&lt;h3 id="emulating-browser-headers"&gt;محاكاة رؤوس المتصفح&lt;/h3&gt;
&lt;p class='pIndent'&gt;الخطوة الأولى والأكثر شيوعًا هي محاكاة رؤوس HTTP الخاصة بالمتصفح بدقة قدر الإمكان. قم بنسخ جميع الرؤوس ذات الصلة من طلب متصفح ناجح.&lt;/p&gt;
&lt;ol class="steps"&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;User-Agent:&lt;/b&gt; استخدم أحدث `User-Agent` من متصفح حقيقي.&lt;/li&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;Accept, Accept-Language, Accept-Encoding:&lt;/b&gt; انسخ هذه الرؤوس كما هي.&lt;/li&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;Referer, Origin:&lt;/b&gt; اضبطها لتعكس المصدر المتوقع للطلب.&lt;/li&gt;
    &lt;li&gt;&lt;b style='color:var(--linkC)'&gt;Cookies:&lt;/b&gt; إذا كانت هناك ملفات تعريف ارتباط ضرورية، قم بإدارتها يدويًا أو باستخدام مكتبات تدعم الجلسات.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-comment='.py' data-source='python-requests-example.py'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على Python requests مع رؤوس متصفح:' &gt;import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'Referer': 'https://example.com/',
    'Origin': 'https://example.com/'
}
response = requests.get('https://api.example.com/data', headers=headers)
print(response.status_code)&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="using-headless-browsers"&gt;استخدام المتصفحات بلا رأس (Headless Browsers)&lt;/h3&gt;
&lt;p class='pIndent'&gt;لتجاوز تحديات JavaScript وملفات تعريف الارتباط المعقدة، استخدم متصفحات بلا رأس مثل &lt;a class='extL' href='https://pptr.dev/' rel='nofollow noreferrer noopener' target='_blank'&gt;Puppeteer&lt;/a&gt; (Node.js) أو &lt;a class='extL' href='https://www.selenium.dev/' rel='nofollow noreferrer noopener' target='_blank'&gt;Selenium&lt;/a&gt; (Python). هذه الأدوات تحاكي متصفحًا حقيقيًا بالكامل، بما في ذلك تنفيذ JavaScript، إدارة ملفات تعريف الارتباط، وحتى حل تحديات CAPTCHA إذا تم تكوينها بشكل صحيح.&lt;/p&gt;
&lt;div class='alert info'&gt;&lt;b&gt;ملاحظة:&lt;/b&gt; استخدام المتصفحات بلا رأس يستهلك موارد حاسوبية وشبكية أكثر بكثير من الطلبات المباشرة، وقد يكون أبطأ في التنفيذ.&lt;/div&gt;

&lt;h3 id="cloudflare-api-tokens-and-ip-whitelisting"&gt;رموز API لـ Cloudflare وقوائم IP البيضاء&lt;/h3&gt;
&lt;p class='pIndent'&gt;إذا كنت المالك أو لديك إذن بالوصول إلى إعدادات Cloudflare للموقع المستهدف، فإن الحل الأمثل هو استخدام &lt;a class='extL' href='https://developers.cloudflare.com/api/tokens/' rel='nofollow noreferrer noopener' target='_blank'&gt;رموز API&lt;/a&gt; أو إضافة عناوين IP الخاصة بخادمك إلى القائمة البيضاء (Whitelist) في قواعد جدار الحماية (Firewall Rules) لـ Cloudflare. هذا يضمن أن طلباتك المباشرة لن يتم حظرها، ويعد النهج الأكثر أمانًا وفعالية.&lt;/p&gt;

&lt;h3 id="rate-limiting-management"&gt;إدارة معدل الطلبات (Rate Limiting)&lt;/h3&gt;
&lt;p class='pIndent'&gt;قد يكون الحظر ناتجًا عن تجاوز حدود معدل الطلبات التي تفرضها Cloudflare. قم بتطبيق تأخيرات (delays) بين الطلبات أو استخدم خوارزميات التراجع الأسي (exponential backoff) لتقليل وتيرة الطلبات، خاصة عند التعامل مع أخطاء &lt;b style='color:var(--linkC)'&gt;HTTP 429 Too Many Requests&lt;/b&gt;.&lt;/p&gt;
&lt;div class='alert warning'&gt;&lt;b&gt;تحذير:&lt;/b&gt; محاولة تجاوز آليات Cloudflare الأمنية دون إذن صريح قد ينتهك شروط الخدمة وقد يؤدي إلى حظر دائم لعنوان IP الخاص بك أو لشبكتك بالكامل. تأكد دائمًا من أنك تعمل ضمن الأطر القانونية والأخلاقية.&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;هل يمكن لـ Cloudflare التمييز بين طلب API من Python وطلب من متصفح حقيقي؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، Cloudflare تستخدم تقنيات متقدمة مثل تحليل رؤوس HTTP، بصمات المتصفح، وتنفيذ JavaScript للتمييز بين الطلبات الشرعية من المتصفحات وتلك الآلية أو التي تأتي من سكربتات.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;ما هو أفضل نهج لتجنب الحظر عند استخدام API خلف Cloudflare؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;النهج الأفضل يعتمد على السيناريو. إذا كان لديك تحكم في إعدادات Cloudflare، استخدم رموز API أو قوائم IP البيضاء. إذا لم يكن كذلك، فحاول محاكاة سلوك المتصفح بدقة قدر الإمكان، أو استخدم متصفحًا بلا رأس (headless browser) إذا كانت تحديات JavaScript معقدة.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/05/cloudflare.html'&gt;Cloudflare وحظر طلبات الـ API المباشرة: حلول هندسية&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>احتراف CSS: من الأساسيات إلى أحدث التطورات</title><link>https://www.siwane.xyz/2026/05/mastering-css.html</link><category>مقالات AI</category><pubDate>Mon, 11 May 2026 10:27:49 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-906345448181342905</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="احتراف CSS: من الأساسيات إلى أحدث التطورات" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;دليل شامل لاحتراف CSS، يغطي الأساسيات المتقدمة وأحدث الميزات مثل استعلامات الحاويات وطبقات التتالي، مع التركيز على التطبيق العملي.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الويب، تُعد لغة CSS (أوراق الأنماط المتتالية) حجر الزاوية لتصميم واجهات المستخدم الجذابة والوظيفية. يتطلب احترافها فهمًا عميقًا للمفاهيم الأساسية ومواكبة التطورات المستمرة التي تُحدث ثورة في طريقة بناء الأنماط. يهدف هذا المقال إلى تقديم مسار عملي لاحتراف CSS وتسليط الضوء على أبرز الميزات الحديثة التي تعزز المرونة والأداء.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="mastering-css-fundamentals"&gt;إتقان أساسيات CSS&lt;/h2&gt;
&lt;p class='pIndent'&gt;لا يمكن احتراف CSS دون فهم راسخ لمبادئها الأساسية. هذه المبادئ هي اللبنات التي تُبنى عليها جميع التصميمات المعقدة.&lt;/p&gt;

&lt;h3 id="selectors-and-specificity"&gt;المحددات والخصوصية&lt;/h3&gt;
&lt;p class='pIndent'&gt;تُعد المحددات (Selectors) الآلية الأساسية لاستهداف عناصر HTML وتطبيق الأنماط عليها. فهم أنواعها (الفئة، المعرف، العنصر، السمة، الزائفة) أمر بالغ الأهمية. ترتبط &lt;b style='color:var(--linkC)'&gt;الخصوصية (Specificity)&lt;/b&gt; ارتباطًا وثيقًا بالمحددات، حيث تحدد القاعدة التي ستُطبق عندما تتضارب عدة قواعد على نفس العنصر. تُحسب الخصوصية بناءً على وزن المحددات (المعرفات &gt; الفئات/السمات &gt; العناصر).&lt;/p&gt;
&lt;pre data-comment='.css' data-source='styles.css'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على الخصوصية:'&gt;
#header h1 { color: blue; } /* خصوصية أعلى */
.main-title { color: red; } /* خصوصية أقل */
&lt;/mark&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="box-model-and-layout"&gt;نموذج الصندوق والتخطيط&lt;/h3&gt;
&lt;p class='pIndent'&gt;يُعد &lt;b style='color:var(--linkC)'&gt;نموذج الصندوق (Box Model)&lt;/b&gt; مفهومًا أساسيًا يصف كيفية عرض عناصر HTML كصناديق مستطيلة، تتكون من المحتوى، الحشوة (padding)، الحدود (border)، والهامش (margin). إتقان هذا النموذج ضروري للتحكم الدقيق في التباعد والمحاذاة.&lt;/p&gt;
&lt;p class='pIndent'&gt;بالإضافة إلى ذلك، تُعد تقنيات التخطيط الحديثة مثل &lt;b style='color:var(--linkC)'&gt;Flexbox&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;CSS Grid&lt;/b&gt; أدوات لا غنى عنها لبناء تخطيطات معقدة ومتجاوبة بسهولة وفعالية. يوفر Flexbox تحكمًا أحادي البعد (صف أو عمود)، بينما يوفر CSS Grid تحكمًا ثنائي الأبعاد (صفوف وأعمدة)، مما يجعله مثاليًا للتخطيطات الشبكية.&lt;/p&gt;
&lt;div class='alert info'&gt;
&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;
يُنصح بالبدء بـ Flexbox للتخطيطات البسيطة ذات البعد الواحد، والانتقال إلى CSS Grid للتخطيطات المعقدة ثنائية الأبعاد.
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="advanced-techniques-and-best-practices"&gt;التقنيات المتقدمة وأفضل الممارسات&lt;/h2&gt;
&lt;p class='pIndent'&gt;بعد إتقان الأساسيات، يمكن للمطورين الانتقال إلى تقنيات أكثر تقدمًا وممارسات تضمن قابلية الصيانة والأداء.&lt;/p&gt;

&lt;h3 id="responsive-design"&gt;التصميم المتجاوب&lt;/h3&gt;
&lt;p class='pIndent'&gt;يُعد &lt;b style='color:var(--linkC)'&gt;التصميم المتجاوب (Responsive Design)&lt;/b&gt; ضرورة قصوى في العصر الحالي لضمان عرض الموقع بشكل مثالي على مختلف الأجهزة وأحجام الشاشات. تُستخدم &lt;b style='color:var(--linkC)'&gt;استعلامات الوسائط (Media Queries)&lt;/b&gt; لتطبيق أنماط مختلفة بناءً على خصائص الجهاز مثل العرض والارتفاع والاتجاه.&lt;/p&gt;
&lt;pre data-comment='.css' data-source='responsive.css'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على استعلام وسائط:'&gt;
@media (max-width: 768px) {
  .container {
    flex-direction: column;
  }
}
&lt;/mark&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;كما تُستخدم الوحدات النسبية مثل &lt;b style='color:var(--linkC)'&gt;`rem`&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;`em`&lt;/b&gt;، بالإضافة إلى وحدات عرض وارتفاع النافذة &lt;b style='color:var(--linkC)'&gt;`vw`&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;`vh`&lt;/b&gt;، لإنشاء تصميمات تتكيف بمرونة.&lt;/p&gt;

&lt;h3 id="css-architecture-and-maintainability"&gt;هندسة CSS وقابلية الصيانة&lt;/h3&gt;
&lt;p class='pIndent'&gt;للحفاظ على قواعد أنماط كبيرة ومنظمة، تُعد منهجيات مثل &lt;b style='color:var(--linkC)'&gt;BEM (Block, Element, Modifier)&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;SMACSS (Scalable and Modular Architecture for CSS)&lt;/b&gt; مفيدة للغاية. تساعد هذه المنهجيات في تنظيم الكود، تقليل التكرار، وتحسين قابلية القراءة والصيانة.&lt;/p&gt;
&lt;p class='pIndent'&gt;تُعد &lt;b style='color:var(--linkC)'&gt;متغيرات CSS (CSS Custom Properties)&lt;/b&gt; أداة قوية لتعريف قيم قابلة لإعادة الاستخدام، مما يسهل إدارة الثيمات وتحديث الأنماط على نطاق واسع.&lt;/p&gt;
&lt;pre data-comment='.css' data-source='variables.css'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على متغيرات CSS:'&gt;
:root {
  &lt;mark class='green'&gt;--primary-color: #007bff;&lt;/mark&gt;
  &lt;mark class='green'&gt;--spacing-unit: 16px;&lt;/mark&gt;
}

.button {
  background-color: &lt;mark class='blue'&gt;var(--primary-color)&lt;/mark&gt;;
  padding: &lt;mark class='blue'&gt;var(--spacing-unit)&lt;/mark&gt;;
}
&lt;/mark&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;hr&gt;

&lt;h2 id="latest-css-developments"&gt;أحدث تطورات CSS&lt;/h2&gt;
&lt;p class='pIndent'&gt;تشهد CSS تطورات مستمرة تُضيف ميزات قوية تعزز قدرات المطورين.&lt;/p&gt;

&lt;h3 id="container-queries"&gt;استعلامات الحاويات (@container)&lt;/h3&gt;
&lt;p class='pIndent'&gt;تُعد &lt;b style='color:var(--linkC)'&gt;استعلامات الحاويات (Container Queries)&lt;/b&gt; ثورة في التصميم المتجاوب. بدلاً من الاستجابة لحجم إطار العرض (viewport)، تسمح استعلامات الحاويات للعناصر بالاستجابة لحجم الحاوية الأصلية التي توجد بداخلها. هذا يوفر مرونة غير مسبوقة في بناء مكونات قابلة لإعادة الاستخدام تتكيف مع سياقها.&lt;/p&gt;
&lt;pre data-comment='.css' data-source='container-queries.css'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على استعلام حاوية:'&gt;
.card-container {
  container-type: inline-size;
}

&lt;mark class='green'&gt;@container (min-width: 400px) {&lt;/mark&gt;
  .card-title {
    font-size: 1.5rem;
  }
  .card-image {
    display: block;
  }
&lt;mark class='green'&gt;}&lt;/mark&gt;
&lt;/mark&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="cascade-layers"&gt;طبقات التتالي (@layer)&lt;/h3&gt;
&lt;p class='pIndent'&gt;تُقدم &lt;b style='color:var(--linkC)'&gt;طبقات التتالي (Cascade Layers)&lt;/b&gt; طريقة جديدة لإدارة خصوصية CSS. تسمح بتنظيم قواعد الأنماط في طبقات، حيث تُطبق الطبقات اللاحقة فوق الطبقات السابقة، بغض النظر عن ترتيبها في ورقة الأنماط أو خصوصية المحددات داخل الطبقة. هذا يمنح المطورين تحكمًا أكبر في التتالي ويقلل من الحاجة إلى استخدام &lt;b style='color:var(--linkC)'&gt;`!important`&lt;/b&gt;.&lt;/p&gt;
&lt;pre data-comment='.css' data-source='cascade-layers.css'&gt;&lt;code&gt;&lt;mark class='block' data-before='مثال على طبقات التتالي:'&gt;
&lt;mark class='green'&gt;@layer base, components, utilities;&lt;/mark&gt;

&lt;mark class='blue'&gt;@layer base {&lt;/mark&gt;
  body { margin: 0; }
&lt;mark class='blue'&gt;}&lt;/mark&gt;

&lt;mark class='red'&gt;@layer components {&lt;/mark&gt;
  .button {
    padding: 10px 20px;
    background-color: blue;
  }
&lt;mark class='red'&gt;}&lt;/mark&gt;

&lt;mark class='orange'&gt;@layer utilities {&lt;/mark&gt;
  .button { /* هذه القاعدة ستتغلب على قاعدة .button في طبقة components */
    background-color: green;
  }
&lt;mark class='orange'&gt;}&lt;/mark&gt;
&lt;/mark&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="new-selectors-and-viewport-units"&gt;محددات جديدة ووحدات عرض جديدة&lt;/h3&gt;
&lt;p class='pIndent'&gt;يُعد المحدد &lt;b style='color:var(--linkC)'&gt;`:has()`&lt;/b&gt; (المحدد الأبوي) إضافة قوية تسمح باستهداف عنصر بناءً على محتواه أو وجود عناصر معينة بداخله. على سبيل المثال، يمكن تحديد عنصر `div` يحتوي على صورة.&lt;/p&gt;
&lt;p class='pIndent'&gt;كما ظهرت وحدات عرض جديدة مثل &lt;b style='color:var(--linkC)'&gt;`dvh`&lt;/b&gt; (dynamic viewport height)، &lt;b style='color:var(--linkC)'&gt;`svh`&lt;/b&gt; (small viewport height)، و &lt;b style='color:var(--linkC)'&gt;`lvh`&lt;/b&gt; (large viewport height) لمعالجة مشكلة شريط العنوان في متصفحات الجوال، مما يوفر تحكمًا أكثر دقة في ارتفاعات العناصر.&lt;/p&gt;

&lt;div class='alert success outline'&gt;
&lt;b&gt;نصيحة!&lt;/b&gt;&lt;br/&gt;
لمواكبة هذه التطورات، يُنصح بمتابعة المدونات التقنية المتخصصة مثل &lt;a class='extL' href='https://css-tricks.com/' rel='nofollow noreferrer noopener' target='_blank'&gt;CSS-Tricks&lt;/a&gt; و &lt;a class='extL' href='https://web.dev/css/' rel='nofollow noreferrer noopener' target='_blank'&gt;web.dev/css&lt;/a&gt;، وتجربة الميزات الجديدة في بيئات التطوير.
&lt;/div&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;ما الفرق الرئيسي بين Flexbox و CSS Grid؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;Flexbox مصمم للتخطيطات أحادية البعد (صف واحد أو عمود واحد)، بينما CSS Grid مصمم للتخطيطات ثنائية الأبعاد (صفوف وأعمدة متعددة)، مما يجعله مثاليًا لتخطيطات الصفحة الكاملة.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;لماذا تُعتبر استعلامات الحاويات مهمة؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;تسمح استعلامات الحاويات للعناصر بالاستجابة لحجم الحاوية الأصلية بدلاً من حجم إطار العرض الكلي، مما يوفر مرونة أكبر في بناء مكونات قابلة لإعادة الاستخدام تتكيف مع سياقها الخاص.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;كيف تساعد طبقات التتالي في إدارة CSS؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;تسمح طبقات التتالي بتنظيم قواعد الأنماط في طبقات ذات أولوية محددة، مما يمنح المطورين تحكمًا أفضل في التتالي ويقلل من مشكلات الخصوصية، خاصة في المشاريع الكبيرة أو عند استخدام مكتبات CSS خارجية.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/05/mastering-css.html'&gt;احتراف CSS: من الأساسيات إلى أحدث التطورات&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>حل مشكلة عدم ظهور صور المصغرات للمشاركات ذات الصلة في بلوجر</title><link>https://www.siwane.xyz/2026/05/b.html</link><category>مقالات AI</category><pubDate>Mon, 4 May 2026 10:27:52 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-3494292201483443830</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="حل مشكلة عدم ظهور صور المصغرات للمشاركات ذات الصلة في بلوجر" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;دليل تقني شامل لحل مشكلة عدم ظهور الصور المصغرة في قسم المشاركات ذات الصلة ببلوجر، مع التركيز على الأسباب والحلول العملية.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; هذا المقال، سنتناول مشكلة شائعة يواجهها العديد من مستخدمي منصة بلوجر (Blogger) وهي عدم ظهور الصور المصغرة (thumbnails) للمشاركات ذات الصلة (Related Posts). تؤثر هذه المشكلة سلبًا على تجربة المستخدم وجمالية المدونة، وقد تشير إلى وجود أخطاء في قالب المدونة أو في طريقة معالجة الصور. سنقدم شروحات تقنية وحلولاً عملية لمعالجة هذه المشكلة.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="understanding-the-problem-and-its-impact"&gt;فهم المشكلة وتأثيرها&lt;/h2&gt;
&lt;p class='pIndent'&gt;تعتبر المشاركات ذات الصلة ميزة حيوية لتحسين تفاعل الزوار داخل المدونة، حيث تشجعهم على استكشاف المزيد من المحتوى ذي الصلة بالمقالة التي يقرؤونها. عندما لا تظهر الصور المصغرة، يصبح القسم أقل جاذبية وقد يتجاهله الزوار، مما يؤدي إلى زيادة معدل الارتداد (Bounce Rate) وتقليل الوقت الذي يقضيه الزائر في الموقع. من الناحية التقنية، غالبًا ما تنبع هذه المشكلة من عدم قدرة الكود البرمجي للقالب على استخراج عنوان URL الصحيح للصورة المصغرة أو من عدم وجود صورة مصغرة قابلة للاستخدام.&lt;/p&gt;
&lt;div class='alert warning outline'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;قبل إجراء أي تعديلات على قالب مدونتك، تأكد دائمًا من أخذ نسخة احتياطية كاملة للقالب. هذا يضمن إمكانية استعادة القالب إلى حالته الأصلية في حال حدوث أي خطأ غير متوقع.&lt;/div&gt;
&lt;h3 id="common-causes-for-missing-thumbnails"&gt;الأسباب الشائعة لعدم ظهور الصور المصغرة&lt;/h3&gt;
&lt;p class='pIndent'&gt;هناك عدة أسباب تقنية وراء عدم ظهور الصور المصغرة، أبرزها:&lt;/p&gt;
&lt;ol class="steps"&gt;
&lt;li&gt;&lt;b&gt;عدم وجود صورة مميزة (Featured Image):&lt;/b&gt; في بعض الأحيان، يعتمد كود المشاركات ذات الصلة على وجود صورة محددة كصورة مميزة للمقالة. إذا لم يتم تعيين صورة كهذه، قد يفشل الكود في العثور على أي صورة لعرضها.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;مشاكل في كود الـ HTML/JavaScript للودجت:&lt;/b&gt; قد يكون الكود المخصص للمشاركات ذات الصلة (سواء كان جزءًا من القالب أو ويدجت مضافًا) يحتوي على أخطاء تمنعه من استخراج `data:post.thumbnailUrl` بشكل صحيح، أو قد لا يتضمن منطقًا للتعامل مع الحالات التي لا تتوفر فيها الصورة المصغرة.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;مشاكل في استضافة الصور:&lt;/b&gt; إذا كانت الصور مستضافة على خدمات خارجية غير متاحة للعامة أو تتطلب مصادقة، فقد لا يتمكن بلوجر من الوصول إليها وعرضها.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;تغييرات في بنية بلوجر:&lt;/b&gt; قد تحدث تحديثات في بنية بلوجر تؤثر على طريقة استدعاء البيانات، مما يتطلب تحديث الكود في القوالب القديمة.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="practical-solutions-and-troubleshooting-steps"&gt;حلول عملية وخطوات استكشاف الأخطاء&lt;/h2&gt;
&lt;p class='pIndent'&gt;لحل مشكلة عدم ظهور الصور المصغرة، اتبع الخطوات التالية بدقة:&lt;/p&gt;
&lt;h3 id="step-1-verify-post-images"&gt;الخطوة 1: التحقق من صور المشاركات&lt;/h3&gt;
&lt;ol class="steps"&gt;
&lt;li&gt;تأكد من أن جميع المشاركات التي تظهر في قسم "المشاركات ذات الصلة" تحتوي على صورة واحدة على الأقل داخل محتواها. يفضل أن تكون الصورة الأولى في المقال هي الصورة التي ترغب في عرضها كصورة مصغرة.&lt;/li&gt;
&lt;li&gt;إذا كانت المشاركة لا تحتوي على صور، قم بإضافة صورة ذات صلة وحفظ المشاركة.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="step-2-inspect-the-related-posts-widget-code"&gt;الخطوة 2: فحص كود ويدجت المشاركات ذات الصلة&lt;/h3&gt;
&lt;p class='pIndent'&gt;هذه هي الخطوة الأكثر أهمية وتتطلب بعض المعرفة الأساسية بـ HTML و XML في قوالب بلوجر.&lt;/p&gt;
&lt;ol class="steps"&gt;
&lt;li&gt;انتقل إلى لوحة تحكم بلوجر &amp;gt; &lt;b style='color:var(--linkC)'&gt;المظهر&lt;/b&gt; &amp;gt; &lt;b style='color:var(--linkC)'&gt;تعديل HTML&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;ابحث عن الكود الخاص بويدجت المشاركات ذات الصلة. غالبًا ما يكون ضمن وسم `&lt;b:widget&gt;` أو `&lt;b:includable&gt;`، وقد يحتوي على كلمات مثل "related posts" أو "similar posts".&lt;/li&gt;
&lt;li&gt;ابحث داخل الكود عن الأجزاء المسؤولة عن عرض الصور. عادةً ما تبحث عن `img` tags أو المتغيرات التي تحمل اسم `thumbnailUrl` أو `post.firstImageUrl`.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class='alert info'&gt;&lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;المتغير القياسي في بلوجر لاستدعاء الصورة المصغرة هو &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;data:post.thumbnailUrl&lt;/code&gt;&lt;/b&gt;. تأكد من أن الكود يستخدم هذا المتغير بشكل صحيح.&lt;/div&gt;
&lt;p class='pIndent'&gt;إذا كان الكود لا يتضمن منطقًا للتعامل مع عدم وجود الصورة المصغرة، يمكنك إضافة شرط للتحقق من وجودها وعرض صورة افتراضية بدلاً منها. إليك مثال على كيفية تعديل الكود:&lt;/p&gt;
&lt;pre data-comment='.html' data-source='src/related-posts-widget.html'&gt;&lt;code&gt;&amp;lt;b:loop values='data:posts' var='post'&amp;gt;
  &amp;lt;div class='related-post-item'&amp;gt;
    &amp;lt;a expr:href='data:post.url'&amp;gt;
      &lt;mark class='block green' data-before='+'&gt;&amp;lt;b:if cond='data:post.thumbnailUrl'&amp;gt;&lt;/mark&gt;
        &amp;lt;img expr:src='data:post.thumbnailUrl' class='related-post-thumbnail'/&amp;gt;
      &lt;mark class='block green' data-before='+'&gt;&amp;lt;b:else/&amp;gt;&lt;/mark&gt;
        &lt;mark class='block green' data-before='+'&gt;&amp;lt;img src='https://4.bp.blogspot.com/-_Y5xQ-1-y-0/AAAAAAAAAAI/AAAAAAAAB/s1600/default-thumbnail.png' class='related-post-thumbnail'/&amp;gt; &amp;lt;!-- استبدل بالرابط الخاص بصورتك الافتراضية --&amp;gt;&lt;/mark&gt;
      &lt;mark class='block green' data-before='+'&gt;&amp;lt;/b:if&amp;gt;&lt;/mark&gt;
      &amp;lt;span class='related-post-title'&amp;gt;&amp;lt;data:post.title/&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/b:loop&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;في هذا المثال، قمنا بإضافة وسم `&lt;b:if&gt;` للتحقق مما إذا كان `data:post.thumbnailUrl` موجودًا. إذا كان كذلك، يتم عرض الصورة المصغرة للمشاركة. وإلا، يتم عرض صورة افتراضية (يجب عليك استبدال الرابط بصورة افتراضية من اختيارك). هذا يضمن ظهور صورة دائمًا، حتى لو لم تكن هناك صورة مصغرة للمشاركة.&lt;/p&gt;
&lt;h3 id="step-3-check-image-hosting-and-accessibility"&gt;الخطوة 3: التحقق من استضافة الصور وإمكانية الوصول إليها&lt;/h3&gt;
&lt;p class='pIndent'&gt;تأكد من أن الصور المستخدمة في مشاركاتك مستضافة بشكل صحيح على بلوجر أو على خدمة استضافة صور عامة. إذا كنت تستخدم صورًا من ألبومات Google Photos (Picasa سابقًا) وكانت هذه الألبومات خاصة، فلن يتمكن بلوجر من عرضها. اجعل الألبومات عامة أو أعد تحميل الصور مباشرة إلى مشاركات بلوجر.&lt;/p&gt;
&lt;h3 id="step-4-javascript-conflicts"&gt;الخطوة 4: تعارضات JavaScript&lt;/h3&gt;
&lt;p class='pIndent'&gt;إذا كان ويدجت المشاركات ذات الصلة يعتمد على كود JavaScript مخصص، فقد تحدث تعارضات مع سكربتات أخرى في القالب. للتحقق من ذلك:&lt;/p&gt;
&lt;ol class="steps"&gt;
&lt;li&gt;افتح مدونتك في المتصفح.&lt;/li&gt;
&lt;li&gt;اضغط على &lt;kbd&gt;F12&lt;/kbd&gt; لفتح أدوات المطور (Developer Tools).&lt;/li&gt;
&lt;li&gt;انتقل إلى تبويب &lt;b style='color:var(--linkC)'&gt;Console&lt;/b&gt;. ابحث عن أي رسائل خطأ باللون الأحمر، والتي قد تشير إلى مشاكل في JavaScript.&lt;/li&gt;
&lt;li&gt;إذا وجدت أخطاء، حاول تعطيل السكربتات المخصصة للمشاركات ذات الصلة مؤقتًا (عن طريق إزالتها أو وضعها داخل تعليق HTML `&lt;!-- ... --&gt;`) لمعرفة ما إذا كانت المشكلة تختفي. إذا اختفت، فهذا يؤكد وجود تعارض.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="step-5-consider-using-a-default-widget"&gt;الخطوة 5: التفكير في استخدام ويدجت افتراضي&lt;/h3&gt;
&lt;p class='pIndent'&gt;إذا استمرت المشكلة بعد تجربة جميع الحلول المذكورة أعلاه، قد يكون الحل الأبسط هو استخدام ويدجت "المشاركات الشائعة" (Popular Posts) الافتراضي من بلوجر، والذي عادةً ما يعرض الصور المصغرة بشكل صحيح. يمكنك إضافة هذا الودجت من لوحة تحكم بلوجر &amp;gt; &lt;b style='color:var(--linkC)'&gt;التخطيط&lt;/b&gt; &amp;gt; &lt;b style='color:var(--linkC)'&gt;إضافة أداة&lt;/b&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="advanced-considerations"&gt;اعتبارات متقدمة&lt;/h2&gt;
&lt;p class='pIndent'&gt;في بعض القوالب المعقدة، قد يتم معالجة الصور المصغرة بواسطة سكربتات خارجية أو وظائف مخصصة داخل القالب. في هذه الحالات، قد تحتاج إلى مراجعة وثائق القالب أو التواصل مع مطور القالب للحصول على دعم فني. تأكد أيضًا من أن القالب الذي تستخدمه متوافق مع أحدث إصدارات بلوجر.&lt;/p&gt;
&lt;div class='alert success'&gt;&lt;b&gt;حل!&lt;/b&gt;&lt;br/&gt;تطبيق التعديلات المذكورة في الخطوة 2، خاصة إضافة الشرط &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;&amp;lt;b:if cond='data:post.thumbnailUrl'&amp;gt;&lt;/code&gt;&lt;/b&gt; مع صورة افتراضية، غالبًا ما يحل المشكلة بشكل فعال ويضمن ظهور الصور المصغرة أو بديلها.&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="frequently-asked-questions"&gt;الأسئلة الشائعة&lt;/h2&gt;
&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;لماذا لا تظهر الصور المصغرة للمشاركات ذات الصلة في مدونتي على بلوجر؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;غالبًا ما يكون السبب هو عدم وجود صورة مميزة في المشاركة، أو خطأ في كود الودجت الخاص بالمشاركات ذات الصلة في قالب HTML، أو مشاكل في استضافة الصور.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;ما هو المتغير الذي يستخدمه بلوجر لعرض الصور المصغرة؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;المتغير القياسي هو &lt;code&gt;data:post.thumbnailUrl&lt;/code&gt;. يجب أن يتضمن كود الودجت الخاص بك هذا المتغير لاستدعاء الصورة المصغرة.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;هل يمكنني تعيين صورة افتراضية إذا لم تكن هناك صورة مصغرة للمشاركة؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;نعم، يمكنك استخدام شرط &lt;code&gt;&amp;lt;b:if cond='data:post.thumbnailUrl'&amp;gt;&lt;/code&gt; في قالب HTML الخاص بك لعرض صورة افتراضية عندما لا تتوفر الصورة المصغرة للمشاركة. راجع الخطوة 2 في هذا المقال للحصول على مثال.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/05/b.html'&gt;حل مشكلة عدم ظهور صور المصغرات للمشاركات ذات الصلة في بلوجر&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>تحويل فتح عنصر &amp;lt;dialog&amp;gt; بانتقال سلس باستخدام Tailwind CSS</title><link>https://www.siwane.xyz/2026/04/tail.html</link><category>مقالات AI</category><pubDate>Mon, 27 Apr 2026 10:28:06 +0100</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-1713415201642942404</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="تحويل فتح عنصر &amp;lt;dialog&amp;gt; بانتقال سلس باستخدام Tailwind CSS" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;

&lt;div class="alert info outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Sawan AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر، وخالٍ من الحشو المزعج.&lt;/div&gt;

&lt;div hidden aria-hidden='true'&gt;شرح تقني دقيق لكيفية تطبيق انتقالات سلسة على فتح وإغلاق عنصر &amp;lt;dialog&amp;gt; الأصلي باستخدام Tailwind CSS و JavaScript.&lt;/div&gt;
&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; تطوير الويب الحديث، أصبح تقديم تجربة مستخدم سلسة أمرًا بالغ الأهمية. عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;dialog&amp;gt;&lt;/b&gt; الأصلي في HTML يوفر طريقة قياسية لعرض مربعات الحوار، لكنه يفتقر إلى آليات الانتقال المدمجة لفتح وإغلاق سلس. يهدف هذا المقال إلى تقديم حل عملي لدمج انتقالات أنيقة باستخدام &lt;b style='color:var(--linkC)'&gt;Tailwind CSS&lt;/b&gt; و JavaScript، مع التركيز على الدقة الهندسية والكفاءة.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="understanding-the-dialog-element-and-its-challenges"&gt;فهم عنصر &amp;lt;dialog&amp;gt; والتحديات&lt;/h2&gt;
&lt;p class='pIndent'&gt;عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;dialog&amp;gt;&lt;/b&gt; هو عنصر HTML دلالي مصمم لتمثيل مربع حوار أو مكون تفاعلي آخر، مثل نافذة منبثقة أو فحص. عند استخدامه مع طريقة &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;showModal()&lt;/code&gt;&lt;/b&gt;، فإنه يفتح مربع الحوار في طبقة علوية، مما يجعله فوق جميع المحتويات الأخرى، ويضيف تلقائيًا خلفية (backdrop) تعتم بقية الصفحة. ومع ذلك، فإن السلوك الافتراضي لفتح وإغلاق مربع الحوار يكون فوريًا، حيث ينتقل من &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;display: none&lt;/code&gt;&lt;/b&gt; إلى &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;display: block&lt;/code&gt;&lt;/b&gt; (أو ما شابه) دون أي تأثير بصري.&lt;/p&gt;
&lt;p class='pIndent'&gt;يكمن التحدي الرئيسي في أن الانتقال المباشر من &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;display: none&lt;/code&gt;&lt;/b&gt; إلى أي قيمة أخرى لا يمكن أن يكون متحركًا (animated) بشكل مباشر باستخدام CSS. لتحقيق انتقال سلس، نحتاج إلى التحكم في خصائص مثل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/b&gt; بينما يكون العنصر مرئيًا بالفعل في DOM، حتى لو كان مخفيًا بصريًا في البداية.&lt;/p&gt;

&lt;h3 id="initial-dialog-structure"&gt;هيكل &amp;lt;dialog&amp;gt; الأولي&lt;/h3&gt;
&lt;p class='pIndent'&gt;لنبدأ بهيكل HTML الأساسي لمربع حوار وزر لفتحه:&lt;/p&gt;
&lt;pre data-comment='.html' data-source='src/index.html'&gt;&lt;code&gt;&amp;lt;button id=&amp;quot;openDialogBtn&amp;quot; class=&amp;quot;bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded&amp;quot;&amp;gt;
  فتح مربع الحوار
&amp;lt;/button&amp;gt;

&amp;lt;dialog id=&amp;quot;myDialog&amp;quot; class=&amp;quot;p-6 rounded-lg shadow-xl bg-white&amp;quot;&amp;gt;
  &amp;lt;h2 class=&amp;quot;text-2xl font-bold mb-4&amp;quot;&amp;gt;عنوان مربع الحوار&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;هذا هو محتوى مربع الحوار الخاص بي.&amp;lt;/p&amp;gt;
  &amp;lt;div class=&amp;quot;mt-6 flex justify-end gap-2&amp;quot;&amp;gt;
    &amp;lt;button id=&amp;quot;closeDialogBtn&amp;quot; class=&amp;quot;bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded&amp;quot;&amp;gt;
      إغلاق
    &amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/dialog&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;hr&gt;

&lt;h2 id="implementing-transitions-with-tailwind-css-and-javascript"&gt;تطبيق الانتقالات باستخدام Tailwind CSS و JavaScript&lt;/h2&gt;
&lt;p class='pIndent'&gt;لتحقيق الانتقال المطلوب، سنقوم بتطبيق فئات Tailwind CSS التي تحدد الحالة الأولية (المخفية) والحالة النهائية (الظاهرة) لمربع الحوار والخلفية. ستقوم JavaScript بعد ذلك بإدارة إضافة وإزالة هذه الفئات، بالإضافة إلى استدعاء طرق &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;showModal()&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/b&gt;.&lt;/p&gt;

&lt;h3 id="tailwind-css-classes-for-transition"&gt;فئات Tailwind CSS للانتقال&lt;/h3&gt;
&lt;p class='pIndent'&gt;سنحتاج إلى فئات لتعريف الحالة الأولية (مخفية) والحالة النهائية (ظاهرة) لمربع الحوار والخلفية. سنستخدم فئات &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/b&gt; من Tailwind CSS.&lt;/p&gt;
&lt;pre data-comment='.css' data-source='src/style.css'&gt;&lt;code&gt;/* تنسيقات عامة للخلفية */
dialog::backdrop {
  &lt;mark class='blue'&gt;@apply bg-black/50 transition-opacity duration-300 ease-out;&lt;/mark&gt;
}

/* حالة الفتح - يتم إضافتها بواسطة JS */
dialog[open]::backdrop {
  &lt;mark class='blue'&gt;@apply opacity-100;&lt;/mark&gt;
}

/* حالة الإغلاق - يتم إزالتها بواسطة JS */
dialog::backdrop {
  &lt;mark class='blue'&gt;@apply opacity-0;&lt;/mark&gt;
}

/* تنسيقات عامة لمربع الحوار */
dialog {
  &lt;mark class='blue'&gt;@apply transition-all duration-300 ease-out;&lt;/mark&gt;
}

/* حالة الفتح - يتم إضافتها بواسطة JS */
dialog.opacity-100.scale-100 {
  &lt;mark class='blue'&gt;@apply opacity-100 scale-100;&lt;/mark&gt;
}

/* حالة الإغلاق - يتم إزالتها بواسطة JS */
dialog:not(.opacity-100.scale-100) {
  &lt;mark class='blue'&gt;@apply opacity-0 scale-95;&lt;/mark&gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;في هذا المثال، نستخدم &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;dialog[open]::backdrop&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;dialog::backdrop&lt;/code&gt;&lt;/b&gt; للتحكم في الخلفية. بالنسبة لمربع الحوار نفسه، سنعتمد على فئات Tailwind المضافة بواسطة JavaScript.&lt;/p&gt;

&lt;h3 id="javascript-for-managing-dialog-state"&gt;JavaScript لإدارة حالة مربع الحوار&lt;/h3&gt;
&lt;p class='pIndent'&gt;تتطلب هذه الطريقة استخدام JavaScript لإدارة فئات CSS وتوقيت استدعاء طرق &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;showModal()&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/b&gt;.&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/script.js'&gt;&lt;code&gt;const dialog = document.getElementById('myDialog');
const openDialogBtn = document.getElementById('openDialogBtn');
const closeDialogBtn = document.getElementById('closeDialogBtn');

// وظيفة لفتح مربع الحوار بانتقال
openDialogBtn.addEventListener('click', () =&gt; {
  dialog.showModal(); // يجعل مربع الحوار مرئيًا (display: block)
  // إضافة فئات الانتقال بعد فترة قصيرة للسماح للمتصفح بتطبيق display: block
  setTimeout(() =&gt; {
    dialog.classList.add('opacity-100', 'scale-100');
    dialog.classList.remove('opacity-0', 'scale-95');
  }, 10); // تأخير صغير جدًا
});

// وظيفة لإغلاق مربع الحوار بانتقال
closeDialogBtn.addEventListener('click', () =&gt; {
  dialog.classList.remove('opacity-100', 'scale-100');
  dialog.classList.add('opacity-0', 'scale-95');

  // إغلاق مربع الحوار بعد انتهاء الانتقال
  dialog.addEventListener('transitionend', function handler() {
    dialog.close();
    dialog.removeEventListener('transitionend', handler); // إزالة المستمع بعد الاستخدام
  }, { once: true });
});

// إغلاق مربع الحوار عند النقر خارج المحتوى (سلوك افتراضي لـ dialog)
dialog.addEventListener('click', (event) =&gt; {
  if (event.target === dialog) {
    closeDialogBtn.click(); // محاكاة النقر على زر الإغلاق
  }
});

// تهيئة الحالة الأولية لمربع الحوار
dialog.classList.add('opacity-0', 'scale-95');
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;في هذا الكود، عند فتح مربع الحوار، نستخدم &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;showModal()&lt;/code&gt;&lt;/b&gt; أولاً، ثم نضيف فئات &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;opacity-100&lt;/code&gt;&lt;/b&gt; و &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;scale-100&lt;/code&gt;&lt;/b&gt; بعد تأخير بسيط. هذا يسمح للمتصفح بتطبيق &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;display: block&lt;/code&gt;&lt;/b&gt; قبل بدء الانتقال البصري. عند الإغلاق، نزيل فئات الحالة المفتوحة ونضيف فئات الحالة المخفية، ثم ننتظر حدث &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;transitionend&lt;/code&gt;&lt;/b&gt; قبل استدعاء &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;dialog.close()&lt;/code&gt;&lt;/b&gt; لضمان إغلاق مربع الحوار بعد اكتمال الانتقال البصري.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="advanced-considerations-and-best-practices"&gt;اعتبارات متقدمة وأفضل الممارسات&lt;/h2&gt;

&lt;h3 id="accessibility-aria"&gt;إمكانية الوصول (ARIA)&lt;/h3&gt;
&lt;p class='pIndent'&gt;عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;dialog&amp;gt;&lt;/b&gt; الأصلي يتمتع بدعم جيد لإمكانية الوصول بشكل افتراضي، حيث يتعامل مع التركيز (focus) و &lt;kbd&gt;Esc&lt;/kbd&gt; لإغلاق مربع الحوار. ومع ذلك، عند تخصيص السلوك باستخدام JavaScript، يجب التأكد من عدم كسر هذه الميزات. الحل المقدم هنا يحافظ على معظم هذه السلوكيات.&lt;/p&gt;

&lt;h3 id="backdrop-transition"&gt;انتقال الخلفية (Backdrop)&lt;/h3&gt;
&lt;p class='pIndent'&gt;يمكن أيضًا تطبيق الانتقالات على الخلفية باستخدام &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;::backdrop&lt;/code&gt;&lt;/b&gt;. في مثالنا، قمنا بتطبيق &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;transition-opacity duration-300 ease-out&lt;/code&gt;&lt;/b&gt; على &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;dialog::backdrop&lt;/code&gt;&lt;/b&gt;. يجب ملاحظة أن &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;dialog::backdrop&lt;/code&gt;&lt;/b&gt; لا يمكن التحكم فيه مباشرة بفئات Tailwind CSS، بل يتطلب استخدام CSS عادي أو تضمين &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;@apply&lt;/code&gt;&lt;/b&gt; داخل ملف CSS الرئيسي لـ Tailwind.&lt;/p&gt;
&lt;div class='alert info outline'&gt;
  &lt;b&gt;معلومة!&lt;/b&gt;&lt;br/&gt;
  تأكد من أن مدة الانتقال في JavaScript (مثل &lt;code&gt;duration-300&lt;/code&gt;) تتطابق مع المدة المحددة في فئات Tailwind CSS لضمان تزامن مثالي بين إغلاق مربع الحوار وانتهاء الانتقال.
&lt;/div&gt;

&lt;h3 id="flexibility-and-customization"&gt;المرونة والتخصيص&lt;/h3&gt;
&lt;p class='pIndent'&gt;يمكن تعديل فئات Tailwind CSS (مثل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;scale-95&lt;/code&gt;&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;translate-y-4&lt;/code&gt;&lt;/b&gt;، &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;duration-300&lt;/code&gt;&lt;/b&gt;) بسهولة لتناسب متطلبات التصميم المختلفة. يمكن أيضًا إضافة انتقالات أخرى مثل &lt;b style='color:var(--linkC)'&gt;&lt;code&gt;transform-gpu&lt;/code&gt;&lt;/b&gt; لتحسين الأداء البصري.&lt;/p&gt;
&lt;p class='pIndent'&gt;باستخدام هذه الطريقة، يمكن للمطورين الاستفادة من قوة عنصر &lt;b style='color:var(--linkC)'&gt;&amp;lt;dialog&amp;gt;&lt;/b&gt; الأصلي مع إضافة لمسة عصرية من الانتقالات السلسة التي توفرها Tailwind CSS، مما يحسن تجربة المستخدم بشكل كبير.&lt;/p&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/04/tail.html'&gt;تحويل فتح عنصر &amp;lt;dialog&amp;gt; بانتقال سلس باستخدام Tailwind CSS&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item><item><title>صمم ونفذ مصادقة مفاتيح API قوية وآمنة لتطبيقات Node.js بفعالية</title><link>https://www.siwane.xyz/2026/03/build-secure-nodejs-api-key.html</link><category>مقالات AI</category><pubDate>Tue, 17 Mar 2026 09:54:39 GMT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5853455075846581201.post-5632736074858971311</guid><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img class="full" alt="صمم ونفذ مصادقة مفاتيح API قوية وآمنة لتطبيقات Node.js بفعالية" src="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s1600/1000009907.webp" /&gt;&lt;/div&gt;


&lt;div hidden aria-hidden='true'&gt;دليل هندسي للمطورين حول بناء نظام مصادقة مفاتيح API آمن وفعال في Node.js و Express.js، مع التركيز على التصميم والتخزين والإدارة.&lt;/div&gt;

&lt;a name='more'&gt;&lt;/a&gt;

&lt;div class="alert outline" style="margin-bottom: 20px;"&gt;&lt;b&gt;شفافية المحتوى:&lt;/b&gt; تم توليد وتنسيق هذا المقال آلياً عبر محرك &lt;b&gt;Siwane AI&lt;/b&gt; لتقديم محتوى تقني دقيق، مباشر.&lt;/div&gt;

&lt;p&gt;&lt;span class='dropCap'&gt;في&lt;/span&gt; عالم تطوير الويب الحديث، تعد واجهات برمجة التطبيقات (APIs) العمود الفقري للتطبيقات الموزعة. يتطلب تأمين هذه الواجهات استراتيجيات مصادقة قوية، وتبرز مصادقة مفاتيح API كحل فعال وبسيط لتطبيقات Node.js. يهدف هذا المقال إلى تقديم دليل هندسي معمق للمطورين حول كيفية تصميم وتنفيذ نظام مصادقة يعتمد على مفاتيح API قوية وآمنة باستخدام Node.js و Express.js.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="key-design-and-secure-storage"&gt;تصميم بنية المفتاح والتخزين الآمن&lt;/h2&gt;
&lt;p class='pIndent'&gt;لضمان أمان نظام المصادقة، يجب أن تبدأ العملية بتصميم مفاتيح API قوية وآمنة، تليها استراتيجيات تخزين لا يمكن اختراقها.&lt;/p&gt;

&lt;h3 id="key-generation"&gt;توليد مفاتيح API قوية&lt;/h3&gt;
&lt;p class='pIndent'&gt;يجب أن تكون مفاتيح API فريدة وغير قابلة للتخمين. نوصي باستخدام &lt;b style='color:var(--linkC)'&gt;سلاسل عشوائية مشفرة&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;معرفات فريدة عالميًا (UUIDs)&lt;/b&gt; كقاعدة للمفتاح. يمكن تحقيق ذلك باستخدام وحدة &lt;a class='extL' href='https://nodejs.org/api/crypto.html' rel='nofollow noreferrer noopener' target='_blank'&gt;`crypto`&lt;/a&gt; المدمجة في Node.js لتوليد بايتات عشوائية ثم تحويلها إلى تنسيق قابل للاستخدام مثل Base64 أو Hexadecimal. يجب أن يكون طول المفتاح كافيًا لضمان التوزيع العشوائي الكافي، عادة ما لا يقل عن 32 بايتًا (256 بت) من العشوائية، مما ينتج عنه سلسلة أطول بكثير عند التشفير.&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/utils/apiKeyGenerator.js'&gt;&lt;code&gt;
const crypto = require('crypto');

function generateApiKey() {
  return crypto.randomBytes(32).toString('hex'); // 32 bytes = 64 hex characters
}

// مثال للاستخدام
&lt;mark class='block blue' data-after='توليد مفتاح API جديد'&gt;const newApiKey = generateApiKey();&lt;/mark&gt;
console.log(newApiKey);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="secure-storage"&gt;التخزين الآمن لمفاتيح API&lt;/h3&gt;
&lt;p class='pIndent'&gt;أحد أهم مبادئ الأمان هو &lt;b style='color:var(--linkC)'&gt;عدم تخزين المفتاح الأصلي أبدًا في قاعدة البيانات&lt;/b&gt; أو أي مكان آخر بعد التوليد الأولي. بدلاً من ذلك، يجب تخزين &lt;b style='color:var(--linkC)'&gt;تجزئة (hash) المفتاح&lt;/b&gt;. تُستخدم خوارزميات التجزئة أحادية الاتجاه مثل &lt;a class='extL' href='https://www.npmjs.com/package/bcrypt' rel='nofollow noreferrer noopener' target='_blank'&gt;`bcrypt`&lt;/a&gt; أو &lt;a class='extL' href='https://www.npmjs.com/package/argon2' rel='nofollow noreferrer noopener' target='_blank'&gt;`Argon2`&lt;/a&gt; لهذا الغرض. هذه الخوارزميات مصممة لتكون بطيئة ومقاومة لهجمات القوة الغاشمة (brute-force attacks) وجداول قوس قزح (rainbow tables).&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/utils/keyHasher.js'&gt;&lt;code&gt;
const bcrypt = require('bcrypt');
const SALT_ROUNDS = 10; // عدد جولات التمليح

async function hashApiKey(apiKey) {
  return await bcrypt.hash(apiKey, SALT_ROUNDS);
}

async function compareApiKey(apiKey, hashedApiKey) {
  return await bcrypt.compare(apiKey, hashedApiKey);
}

// مثال للاستخدام
async function example() {
  const newApiKey = generateApiKey(); // من الدالة السابقة
  &lt;mark class='block blue' data-after='تجزئة المفتاح قبل التخزين'&gt;const hashedKey = await hashApiKey(newApiKey);&lt;/mark&gt;
  // تخزين hashedKey في قاعدة البيانات
  console.log('Hashed Key:', hashedKey);

  // عند المصادقة:
  &lt;mark class='block blue' data-after='التحقق من المفتاح'&gt;const isValid = await compareApiKey(newApiKey, hashedKey);&lt;/mark&gt;
  console.log('Is Valid:', isValid);
}
example();
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='note wr'&gt;&lt;b&gt;تحذير!&lt;/b&gt;&lt;br/&gt;يجب التأكد من أن المفتاح الأصلي لا يُعرض للمستخدم إلا مرة واحدة عند إنشائه، ولا يتم تسجيله أو تخزينه في أي مكان.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id="authentication-implementation-and-key-management"&gt;تنفيذ المصادقة وإدارة المفاتيح&lt;/h2&gt;
&lt;p class='pIndent'&gt;بعد تصميم المفاتيح وتخزينها بأمان، ننتقل إلى تنفيذ آلية المصادقة وإدارة دورة حياة المفتاح.&lt;/p&gt;

&lt;h3 id="authentication-middleware"&gt;بناء Middleware للمصادقة&lt;/h3&gt;
&lt;p class='pIndent'&gt;في Express.js، يمكن بناء &lt;b style='color:var(--linkC)'&gt;middleware فعال&lt;/b&gt; لاعتراض الطلبات الواردة والتحقق من مفتاح API. يتم استخراج المفتاح عادة من رأس HTTP، مثل &lt;a class='extL alt' href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-API-Key' rel='nofollow noreferrer noopener' target='_blank'&gt;`x-api-key`&lt;/a&gt; أو &lt;a class='extL alt' href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization' rel='nofollow noreferrer noopener' target='_blank'&gt;`Authorization: ApiKey &amp;lt;key&amp;gt;`&lt;/a&gt;. يقوم الـ middleware بعد ذلك بالبحث عن المفتاح المقابل في قاعدة البيانات ومقارنة التجزئات.&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/middleware/apiKeyAuth.js'&gt;&lt;code&gt;
const { compareApiKey } = require('../utils/keyHasher');
// افتراض دالة لجلب المفتاح المجزأ من قاعدة البيانات
// function getHashedApiKeyFromDB(apiKeyId) { ... }

async function apiKeyAuth(req, res, next) {
  const apiKey = req.headers['x-api-key'] || req.headers['authorization']?.split(' ')[1];

  if (!apiKey) {
    return res.status(401).json({ message: 'API Key missing' });
  }

  try {
    // في بيئة إنتاجية، ستبحث عن المفتاح المجزأ المرتبط بـ apiKey
    // هنا، نفترض أن لدينا مفتاح مجزأ مخزن مسبقًا للمقارنة
    &lt;mark class='block blue' data-after='جلب المفتاح المجزأ من قاعدة البيانات بناءً على معرف المفتاح أو جزء منه'&gt;const storedHashedKey = '$2b$10$EXAMPLE_HASH_FROM_DB'; // استبدل بهذا من DB&lt;/mark&gt;

    &lt;mark class='block green' data-after='مقارنة المفتاح المقدم مع المفتاح المجزأ المخزن'&gt;const isValid = await compareApiKey(apiKey, storedHashedKey);&lt;/mark&gt;

    if (isValid) {
      // يمكن إضافة معلومات المستخدم/العميل إلى req.user أو req.client
      next();
    } else {
      res.status(403).json({ message: 'Invalid API Key' });
    }
  } catch (error) {
    console.error('API Key authentication error:', error);
    res.status(500).json({ message: 'Internal server error' });
  }
}

module.exports = apiKeyAuth;
&lt;/code&gt;&lt;/pre&gt;
&lt;p class='pIndent'&gt;يمكن استخدام هذا الـ middleware في تطبيق Express.js كالتالي:&lt;/p&gt;
&lt;pre data-comment='.js' data-source='src/app.js'&gt;&lt;code&gt;
const express = require('express');
const apiKeyAuth = require('./middleware/apiKeyAuth');
const app = express();

app.use(express.json());

&lt;mark class='block green' data-after='تطبيق middleware على مسار معين أو على جميع المسارات'&gt;app.get('/protected-route', apiKeyAuth, (req, res) =&gt; {&lt;/mark&gt;
  res.json({ message: 'Welcome, authenticated user!' });
});

app.listen(3000, () =&gt; console.log('Server running on port 3000'));
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="key-lifecycle-management"&gt;إدارة دورة حياة المفتاح (Key Lifecycle Management)&lt;/h3&gt;
&lt;p class='pIndent'&gt;تعد إدارة دورة حياة المفتاح جزءًا حيويًا من استراتيجية أمنية شاملة:&lt;/p&gt;
&lt;ol class="steps"&gt;
    &lt;li&gt;&lt;b&gt;التجديد (Rotation):&lt;/b&gt; يجب تشجيع المستخدمين على تجديد مفاتيح API بانتظام أو فرض ذلك تلقائيًا. هذا يقلل من نافذة التعرض للمفتاح المخترق.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;الإلغاء (Revocation):&lt;/b&gt; يجب توفير آلية فورية لإلغاء المفاتيح عند الاشتباه في اختراقها أو عدم الحاجة إليها. يمكن تحقيق ذلك عن طريق وضع علامة "غير نشط" في قاعدة البيانات أو حذف التجزئة.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تحديد الصلاحية (Expiry):&lt;/b&gt; يمكن تعيين تاريخ انتهاء صلاحية للمفاتيح، مما يتطلب من المستخدمين تجديدها قبل انتهاء الصلاحية. هذا يضيف طبقة أخرى من الأمان.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class='alert info'&gt;
    لتحقيق إدارة فعالة، يجب أن يتضمن نموذج قاعدة البيانات الخاص بمفاتيح API حقولًا مثل `isActive` (منطقي)، `expiresAt` (تاريخ ووقت)، و`createdAt` (تاريخ ووقت).
&lt;/div&gt;

&lt;hr&gt;

&lt;h2 id="security-best-practices-and-challenges"&gt;أفضل الممارسات الأمنية والتحديات&lt;/h2&gt;
&lt;p class='pIndent'&gt;بالإضافة إلى التنفيذ الأساسي، هناك تحديات أمنية شائعة يجب التخفيف منها لضمان نظام قوي.&lt;/p&gt;

&lt;h3 id="mitigating-threats"&gt;التخفيف من التهديدات الأمنية&lt;/h3&gt;
&lt;ul class='steps'&gt;
    &lt;li&gt;&lt;b&gt;هجمات التخمين (Brute-Force):&lt;/b&gt; تنفيذ &lt;b style='color:var(--linkC)'&gt;تحديد المعدل (Rate Limiting)&lt;/b&gt; على نقطة نهاية المصادقة أو على جميع نقاط النهاية المحمية. يمكن استخدام مكتبات مثل &lt;a class='extL sec' href='https://www.npmjs.com/package/express-rate-limit' rel='nofollow noreferrer noopener' target='_blank'&gt;`express-rate-limit`&lt;/a&gt;.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;إعادة استخدام المفاتيح:&lt;/b&gt; تشجيع أو فرض استخدام مفاتيح فريدة لكل تطبيق أو خدمة، وتجنب مشاركة المفاتيح بين بيئات مختلفة (تطوير، اختبار، إنتاج).&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تأمين نقاط النهاية عبر قيود الوصول:&lt;/b&gt; تطبيق &lt;b style='color:var(--linkC)'&gt;التحكم في الوصول المستند إلى الأدوار (RBAC)&lt;/b&gt; أو &lt;b style='color:var(--linkC)'&gt;قوائم التحكم في الوصول (ACLs)&lt;/b&gt; لضمان أن المفتاح المصادق عليه لديه فقط الأذونات اللازمة للوصول إلى الموارد المحددة.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;تسجيل ومراقبة الوصول:&lt;/b&gt; تسجيل جميع محاولات المصادقة الناجحة والفاشلة، ومراقبة هذه السجلات للكشف عن الأنشطة المشبوهة.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class='showH' itemscope itemtype='https://schema.org/FAQPage'&gt;
&lt;details class='ac' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;هل يمكن استخدام مفاتيح API كبديل لـ OAuth2؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;مفاتيح API مناسبة للمصادقة من خادم إلى خادم أو للتطبيقات التي لا تتطلب تفاعل المستخدم المباشر للمصادقة. OAuth2 أكثر ملاءمة للمصادقة التفويضية حيث يحتاج المستخدم إلى منح تطبيق طرف ثالث إذن الوصول إلى موارده دون مشاركة بيانات اعتماده.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;details class='ac alt' itemscope itemprop='mainEntity' itemtype='https://schema.org/Question'&gt;
&lt;summary itemprop='name'&gt;ما هي المخاطر الرئيسية لتخزين مفاتيح API كنص واضح؟&lt;/summary&gt;
&lt;div itemscope itemprop='acceptedAnswer' itemtype='https://schema.org/Answer'&gt;&lt;p itemprop='text'&gt;تخزين مفاتيح API كنص واضح يعرضها للخطر الشديد. في حالة اختراق قاعدة البيانات، سيتمكن المهاجمون من الوصول الفوري إلى جميع المفاتيح، مما يمكنهم من انتحال هوية المستخدمين أو التطبيقات والوصول إلى الموارد المحمية. التجزئة (hashing) تحمي من هذا السيناريو.&lt;/p&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;

&lt;details class='sp arp' open&gt;
&lt;summary data-show='عرض الكل' data-hide='إخفاء الكل'&gt;المشاركات ذات الصلة&lt;/summary&gt; 
&lt;div class='aRel'&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p class='pRef'&gt;المقال الأصلي:&lt;br&gt; &lt;a href='https://www.siwane.xyz/2026/03/build-secure-nodejs-api-key.html'&gt;صمم ونفذ مصادقة مفاتيح API قوية وآمنة لتطبيقات Node.js بفعالية&lt;/a&gt;&lt;br&gt;المصدر: &lt;a href='https://siwane.xyz' target='_blank'&gt;صوان محور XYZ&lt;/a&gt;&lt;br&gt; شكر خاص لـ GEMINI و جمال الحزازي.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;https://www.siwane.xyz/feeds/posts/default?orderby=UPDATED&lt;/div&gt;</description><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R2vZ2xl/AVvXsEiH7bQC9iosnT-I7_ySGGh_8IH-50cBBZf6YPfbcSNe_nqWyE3DTLqea7a4ftkA5xUWWQt2Web3sFvFxPVDnLrJAjhP7WqTQESi_m7lj3j77odTcvwWdJeVvxO18rWQY7luZWNgbk5T9yIN3d_bKYGmD0FHqk7l_ljaGbdU1kFKJLNZ1F9U3VV-gmO0iWY/s72-c/1000009907.webp" width="72"/><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><author>jamal@elhizazi.me (صِوان مِحور الابعاد الثلاث XYZ)</author></item></channel></rss>