Nuhla Almasri
الأعضاء-
المساهمات
122 -
تاريخ الانضمام
-
تاريخ آخر زيارة
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Nuhla Almasri
-
يمكنك استخدام مكتبة جاهزة للCaptcha من الjquery كالتالي <!-- captcha challenge: placeholder --> <div id="botdetect-captcha" data-captchastylename="jqueryFormCaptcha"></div> <label> <span>Retype the characters from the picture:</span> <!-- captcha code: user-input textbox --> <input type="text" id="userCaptchaInput" > </label> <script src="node_modules/jquery/jquery.min.js"></script> <script src="node_modules/jquery-captcha/dist/jquery-captcha.min.js"></script> و هنا تقوم بعمل تصديق على صحة الأدخال كالتالي // إنشاء نسخة captcha للواجهة الأمامية في معالج الأحداث DOM. // وقم بتعيين خاصية captchaEndpoint للإشارة إلى // مسار نقطة نهاية اختبار captcha على الواجهة الخلفية لتطبيقك var captcha = $('#botdetect-captcha').captcha({ captchaEndpoint: 'simple-captcha-endpoint.ashx' }); $('#contactForm').submit(function (event) { if (isNameValid && isEmailValid && isSubjectValid && isMessageValid) { // الحصول على قيمة كود // captcha التي أدخلها المستخدم ليتم التحقق من صحتها في الجانب الخلفي var userEnteredCaptchaCode = captcha.getUserEnteredCaptchaCode(); // الحصول على معرف مثيل captcha الذي حاول المستخدم حله var captchaId = captcha.getCaptchaId(); var postData = { name: $('#name').val(), email: $('#email').val(), subject: $('#subject').val(), message: $('#message').val(), userEnteredCaptchaCode: userEnteredCaptchaCode, captchaId: captchaId }; ..... ..... /// هنا تقوم بعملية ‘إرسال البيانات أو أي عملية تحتاجها } و هنالك طريقة أخرى و هي عيارة عن خلق canvas و رسم أحرف بطريقة عشوائية و تتمكن من خلالها أن تحدد المدخلات التي تريدها كالتالي : // يتم استخدام document.querySelector () لتحديد عنصر من المستند باستخدام المعرف الخاص به let captchaText = document.querySelector('#captcha'); var ctx = captchaText.getContext("2d"); ctx.font = "30px Roboto"; ctx.fillStyle = "#08e5ff"; let userText = document.querySelector('#textBox'); let submitButton = document.querySelector('#submitButton'); let output = document.querySelector('#output'); // يحتوي alphaNums على الأحرف التي تريد إنشاء CAPTCHA بها let alphaNums = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; let emptyArr = []; // تولد هذه الحلقة سلسلة عشوائية من 7 أحرف باستخدام alphaNums // علاوة على ذلك ، يتم عرض هذه السلسلة على أنها CAPTCHA for (let i = 1; i <= 7; i++) { emptyArr.push(alphaNums[Math.floor(Math.random() * alphaNums.length)]); } var c = emptyArr.join(''); //هنا تقوم برسم الcanvas // و يحتوي على الاحر المرادة ctx.fillText(emptyArr.join(''),captchaText.width/4, captchaText.height/2); // هنا دالة تقوم بعمل النصديق على ال البانات المدخلة submitButton.addEventListener('click', function() { // هنا نقوم بالمقارنة بين القيمة المدخلة و القيمة التي تم عرضها و على أساسها نخبر المستحدم أن كانت صحيحة أم لا if (userText.value === c) { output.classList.add("correctCaptcha"); output.innerHTML = "Correct!"; } else { output.classList.add("incorrectCaptcha"); output.innerHTML = "Incorrect, please try again"; } });
-
أنت تستخدم الPHP و أختلاف طريقة كتابة الكود لا يختلف بأستعماله لكل لغة طريقة معينىة بتطبيق نفس الكود ما ارسلته انا هو بال Javascript , nodeJs لكن المهم أن الطريقة المستخدمة تخدمك فقط لأستدعاء بيانات من السيرفير و ليس لأرسال أو تعديل البينات بالسيرفير وإن أحتجت لتعديل أو أرسال بيانات ستحتاج الى أستعمال http Request. أستخدام الSSE هو لتقليل الثقل على السيرفر كما ذكرنا و هذا ما انت تريده
- 6 اجابة
-
- 1
-
// هكذا يتم تعريف الSSE // من جهة السيرفير لاحظ أنه لا يستقبل أي داتا و ضمنيا فقط يستقبل رقم المستخدم و أسم الأيفينت // هنا تعريف الEventHandler // لل SSE function eventsHandler(request, response, next) { const headers = { 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive', 'Cache-Control': 'no-cache' }; response.writeHead(200, headers); const data = `data: ${JSON.stringify(facts)}\n\n`; response.write(data); const clientId = Date.now(); // هنا نقوم بإعطاء المستخدم ID // و يتم المصادقة فقط مره واحدة const newClient = { id: clientId, response }; clients.push(newClient); request.on('close', () => { console.log(`${clientId} Connection closed`); clients = clients.filter(client => client.id !== clientId); }); } // و هنا نستخدم أسم ال EVENTHANDLER // الذي نريد تنفيدذه app.get('/events', eventsHandler); و من جهة المستخدم يقوم بإستدعاء الدالة مرارا و تكرار حسب إسم الروات التي تقوم بأستدعاء الSSE eventHandler
-
نظام الSSE ليس لتعديل البيانات و بعث بيانات يعتبر نظام الSSE مثال على إرسال البيانات من إتجاه واحد فقط من ناحية الServer فقط لذلك لا يمكنك إرسال أي معلومات الى السيرفير سوى للقيام بعمل HandChaking أي خلق أتصال بين السيرفر و التطبيق مثال على أستعمال هذه الطريقة هي Notification أي جلب أي معلومات يتم تحديثها بأستمرار . نظام الSEE يشبه كثيرا ال WebSocket الا أن WebSockets تختلف بحيث أنها ترسل و تستقبل معلومات من و إالى السيرفر أما الSSE فقط يرسل من السيرفير الى التطبيق و أن أرسلت معلومات زائدة عن رقم ال CLIENT أو إسم الEVENT .. الخ, فسوف يتم تجاهلها عملية إرسال المعلومات من السيرفير الى التطبيق عدة مرات لن يقوم بغلق السيرفير و لن يكون تدفق المعلومات عبئ على الشبكة بحيث أنه لن يتم إرسال المعلومات من السيرفير الى المتصفح أو الهاتف بشكل مستمر بالرغم من أن الأتصال يبقى مفتوح بحيث أولا لا يوجد أرسال سوى بأتجاه واحد فقط كما أن عملية التصافح HandChacking تحدث مرة واحدة فقط و أيضا الأتصال ممكن أن يتم أيقافه مؤقتا إن لم يكن المستخدم active لذلك لن يكون هناك تاثير كبير على عمل السيرفير أن كان هنالك الألاف من الستخدمين و لهذه المشكلة تم تصميم هذه النظام
-
type hints هي طريقة لأعطاء البايثون دلالة للقيمة الراجعة أو حتى الأصناق على القيمة المحتملة التيى تقوم ببناءها و هي طرdقة جيدة لمساعدة ال type checkers للبايثون بحيث أنه بهذه الطريقة يقوم بمعرفة ماذا يجب أن تمرر أو أن ترجع و من هنا يستطيع ال type checkers بسهولة أن يخمن إن كنت تقوم بإرسال صنف غير متوقع و مثال على هذا الموضوع التالي : def headline(text, align=True): if align: return f"{text.title()}\n{'-' * len(text)}" else: return f" {text.title()} ".center(50, "o") print(headline("python type checking")) print(headline("python type checking", align=False)) #--------------- أضف الآن تلميحات الكتابة عن طريق التعليق على الوسيطات وقيمة الإرجاع على النحو التالي: def headline(text: str, align: bool = True) -> str:# هنا نقوم بتحديد الصنف للقيمة الراجعة لتسهيل عملية التحمين if align: return f"{text.title()}\n{'-' * len(text)}" else: return f" {text.title()} ".center(50, "o") print(headline("python type checking", align="left")) print(headline("python type checking", align="center"))
- 2 اجابة
-
- 1
-
تعتبر write, writefile من الدوال low-level access أي هي وسيلة سريعة لكتابة بعض المعلومات على ملف و لكن الفرق بين write , writeFile هو أن writeFile تقوم بفتح و كتابة و أغلاق الملف دون الحاجة الى أستعمال أي أمر أخر أما write فلا تقوم بأغلاق الملف و عليك أغلاقة أما بالنسبة لل fs.createWriteStream بالمقارنة مع السابقات فهي من الدوال الأعلى قدرة على الحفظ بطريقة دقيقة حيث أنها تفتح مجرى stream ليقوم بتدفق المعلومات من الى الملف بشكل طوابير queues و بهذه الطريقة فأن هذه الطريقة تتيح لك كتابة ملفات بحجم أكبر و أدق من الدوال السابقة حيث أن write, weiteFile ليسو عمليين حينما تقوم بكتابة ملفات كبيرة الحجم
- 3 اجابة
-
- 1
-
ما عليك سوى جعل الماركر Draggable كالتالي var marker = new google.maps.Marker({ position: myLatlng, map: map, draggable:true, title:"Drag me!" }); و من هنا يمكنك أضافة EventListener للعلامة يقوم مثلا بطباعة القيمة كالتالي marker.addListener('dragged', printMarkerLocation); function printMarkerLocation(){ console.log('Lat: ' + marker.position.lat() + ' Lng:' + marker.position.lng() );}
-
البدائل تكمن بأستعمال Clouds مثلا S3 AWS, Firestore ,googlecloud و أماكن تخزين كثيرة و لها API's خاصة بها و كيفية إستعمالها و لكن إن كان السيرفير الذي تقوم بتحميل الملفات اليه يمكنك من تحميل حجم لا بأس به من الصور و الفيديو فيمكنك الإستغناء عن هذه ال API's
- 2 اجابة
-
- 1
-
أولا عملية معالجة الأخطاء تحتاج الى تنفيذ أمور معينة على قاعدة البيانات بحيث أنه لن يتبين لك ما هية الأخطاء سوي عندما تقوم بعملية ادخال أو تعديل أو حذف هنا يتبين لك ما الحاطاء التي تحدث بكل الأحوال عند القيام بعمل دالة تقوم بإدخال بيان الى قاعدة البيانات فمن المهم دائما القيام بعمل try ... catch مثال على ذلك مايلي // هنا نقووم بتعريف الدالة التي تقوم بإدخال البيان function InsertData(doc, cd /* هذه دالة أخرى نقوم بتمريرها و أحذ الناتج منها سواؤ كانت خطأ أو الأدخال تم بشكل صحيح*/){ try { collection.Insert(doc); // هنا نقوم بأستعمال إسم الدالة التي قمنا بتمريرها و تمرير أن النتيجة صحيحية cd({result:"Done"},null) } catch (MongoWriteConcernException ex) { if (ex.Code == 11000) //هنا يمكنك أن تقوم بعمل exception //throw new YourConflictException("User already exists for username and/or email"); // أو بأرسال الخطأعن طريق الدالة كالتالي cd(null,{error:"MongoWriteConcernException") else // throw ex; cd(null,{error:"Other Exceptions") } } // و هنا الدالة نستخدمها مثلا بال Controllers // بالشكل النالي InsertData(doc, function(data, error){ // طبعا هنا يمكنك أن تحدد نوع ال statuse if(error) res.send(error) // طبعا هنا يمكنك أن تحدد نوع ال statuse res.send(data) })
-
إستعملت نفس الطريقة و لا يوجد بها أي ضرر خصوصا أن الرئاكت يستعمل virtual Dom أي أنه لا يقوم بإرسال الصفحة كامله بل يرسل التغييرات و يتم أستقبالها و تعديل هذه التغييرات بشجرة الdom
-
على الأغلب طريقة إرسال FormData خاطئة عند أرسال صورة عن طريق ال Formdata عليك تحديد ContantTypr ب 'multipart/form-data' الرجاء محاول إرسال المعلومات بالطريقة التالية بدلا مما سبق var formData = new FormData(); formData.append('profileImg', this.state.profileImg, this.state.title) console.log(formData); axios({ method: "post", url: "/api/posts", data: formData, headers: { "Content-Type": "multipart/form-data" }, }) .then(function (response) { //handle success console.log(response); }) .catch(function (response) { //handle error console.log(response); });
-
يمكنك إستخدام Regular Expressions بحيث تجد جميع الأحرف كمصفوفة و من ثم تقوم بتحويل هذه المصفوفة الى string و بطريقة سلهة جدا كالتالي import re word1 = " ".join(re.findall("[a-zA-Z]+", st)) و إن أردت أيضا الأرقام فيمكنك إضافة 0-9 داخل الأقواس فيتم جلب الأرقام أيضا
- 2 اجابة
-
- 1
-
من المعروف أن أي دالة تصف ب statice تكون تنتمي للصنف و ليس لاوبجت من ذلك الصنف بما معناه إننا نستطيع إستدعاء الدالة فقط بكتابة إسم الصنف دون عمل instance منه أي خلق أوبجت كالتالي class A(object): def foo(self, x): print(f"executing foo({self}, {x})") @classmethod def class_foo(cls, x): print(f"executing class_foo({cls}, {x})") @staticmethod def static_foo(x): print(f"executing static_foo({x})") #هنا نقوم بخلق أوبجكت أو وحده من هذا الصنف a = A() #يمكننا هنا أستدعاء الclassmethod #بهذه الطريقة فقط a.class_foo(1) # static_fooأما ال #فهي تنتمي فقط للكلاس و ليس للأوبجت لذلك يتم أستدعائها من عن طريق إسم الكلاس #كالتالي A.static_foo('hi') كما أن الclassmethod تمكنك من تغيير الجالة للأوبجكت الstaticmethod لا تستطيع بها أنم تقوم بتغيير أي حالة و ليس لها علم بأي معلومات عن الأوبجكت و كما نرى classmethos تاخذ cls كمتغير يمرر اليها و يجب تمريره أما الstaticmethod فليس شرط أن تأخذ أي متغير
- 2 اجابة
-
- 1
-
هنا مثال صغير لحفظ المعلومات داخل ال shredprefrences طبعا الحال state تكون عن طريق ال blocs , redux و كثير من مكتبات تنظيم الأحوال //هنا نقوم بحفظ الحال الى الجهاز ك file void saveToPrefs(AppState state) async { // نستدعي الshredprefrrences SharedPreferences preferences = await SharedPreferences.getInstance(); // ناخذ قيمة الحال بعد تحويلها و نقوم بتخزينها بالملف var string = json.encode(state.toJson()); writeFile(string); // و هنا نقوم بحفظ المعلومات داخل ال sharedprefrences await preferences.setString('AlbumsState', string); }
- 5 اجابة
-
- 1
-
يمكنك استخدام litsql يتم تحميلها بنفس التطبيق او خفظه كملف json يتم حفظه ب SharedRefrences و عند طلب المعلومات يمكنك الأستعانة بهذا الملف أو ال litsql و استخراج البيانات منها
- 5 اجابة
-
- 2
-
لغة البايثون سهلة التعلم و لكن صنع الألعاب يحتاج الى وقت و مهارة ليس فقط بالبرمجة و أيضا modelling أن كانت 3D و رسم أن كانت 2D يجب عليك تحديد الألعاب التي تود صنعها فهنالك برامج كثيرة تمكنك من عمل ألعاب و محركات خاصة لها مثل يونتي و ريل انجن كما عليك أن تفكر هل تود عمل ألعاب للهاتف أو للويب فهنالك أختلافات بينهم و قد تضطر الى تعلم لغة أخرى عند تحديد نوع الأألعاب التي تود خلقها مثال على ذلك يونتي يستخدم لغة C# , Javascript بالنسبة للآلة المستخدمة بالبرمجة فالافضل دائما إستخدام حاسوب خصوصا أنك تحتاج برامج خاصة لتقوم ببناء تطبيق كما تحتاج الى معالج قوي لعمل العمليات الحسابية و هذا غير متوفر بالهاتف أما بالنسبة للتعلم فيمكنك و لكن عند التطبيق فلا يمكن أتمام برنامج من خلال الهاتف بالنسبة للوقت على أقل تقدير تحتاج 4 ساعات يوميا أن كنت تود بأسراع عملية التعلم و هذا متوسط حيث أن البرمجة تحتاج الى تطبيق أكثر من فقط قراءة و التطبيق بالبداية قد يخلق أخطاء عدة قد لا تكون على دراية بها و لكنها مع الوقت سيصبح لك معرفة بها و تستطيع تجنبها
-
بإمكانك إستخدام مكتبة تدعي signal هذه المكتبة تقوم بتتبع دالة معينة و من ثم توقيفها او عمل أي شيئ أخر بعد مرور وقت معين انت تقوم بتعريفه لها التالي طريقة خلق صنف قائم على هذه المكتبة و المثال الذي يليه سيكون كيفية أستخدام هذا الصنف from functools import wraps import errno import os import signal #هنا نعرف الصنف و هو يرث من Exeptions class TimeoutError(Exception): pass #هنا نعرف الدالة الني سنقوم بأستخدامها لتقفي الوقت و أنهاء أي دالة تقوم انت تريده يعد هذا الوقت def timeout(seconds=10, error_message=os.strerror(errno.ETIME)): #هنا نعرف المزين def decorator(func): #داخل المزين نقوم بتعريف الدوال التي تقوم بالتعرف على الدوال الخارجية و كيفية التعامل معها def _handle_timeout(signum, frame): raise TimeoutError(error_message) def wrapper(*args, **kwargs): signal.signal(signal.SIGALRM, _handle_timeout) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return wraps(func)(wrapper) return decorator هنا سنقوم بإستخدام هذا الصنف لايقاف دالة بعد فترة من الوقت كالتالي : from timeout import timeout # مهلة وظيفة تشغيل طويلة مع انتهاء صلاحية افتراضي يبلغ 10 ثوانٍ. @timeout def long_running_function1(): ... # مهلة بعد 5 ثوان @timeout(5) def long_running_function2(): ... # انتهت المهلة بعد 30 ثانية ، مع ظهور الخطأ "انتهت مهلة الاتصال" @timeout(30, os.strerror(errno.ETIMEDOUT)) def long_running_function3():
-
يمكنك أستخدام مكبة Regular Expression كالتالي #نقوم بإستيراد المكتبة import re #نعرف القيمة التي بحث داخلها s = "Hello my Jawwal number is 0590000001" #نقوم بالبحث عن هذا الرمز و هو يدل على أن أول 3 احرف ستكون 059 و الباقي يجب أن تكون 7 أرقام re.findall(r"^059[\d]{4,9}", s)
- 2 اجابة
-
- 1
-
يمكنك أستخدام Regular Expressions (Regex) أو التعبيرات العادية مثال عليه import re pattern = r"Cookie" sequence = "Cookie" if re.match(pattern, sequence): print("Match!") else: print("Not a match!") أن بعض المتغيرات للتعبيرات العادية قد تكون بعض الشيئ غير واضحة و لكن سأرفق هنا صورة لبعض الأشارات و دلالاتها
- 5 اجابة
-
- 1
-
هذه المحددات لمعرفة كيفية تعامل الأصناف مع بعضها و كيفبة الوصول الى المتغيرات و الدوال من صنف معين private هو محدد يمنع أي صنف أخر من أستخدام هذه الدالة أو المتغير و لا يمكن أستدعئها من خارج الصنف هي فقط تعمل داخليا . public تمكنك من أستخدام الدالة أو المتغير من خلال أي صنف أخر و هنا مثال عليها كالتالي package p1; public class Demo1 { public void show() { System.out.println("Javatpoint"); } } import p1.*; class Demo2 { public static void main(String args[]) { Demo1 obj = new Demo1(); obj.show(); } } // هنا لن سيقوم بطباعة الأمر خصوصا بدون أي أخطاء لكن أم قمنا بتغيير المحدد الى private //فسيقوم بأعطاء خطأ لانه لا يسمح لك بأستخدام هذه الدالة خارج الصنف نفسه // كالتالي package p1; public class Demo1 { private void show() { System.out.println("Javatpoint"); } } import p1.*; class Demo2 { public static void main(String args[]) { Demo1 obj = new Demo1(); obj.show(); } } // سيخرج لك هذه المشكلة // error: show() has private access in demo1 .... أما بالنسبة للمحدد protected قهل لاحظت أننا نستعمل كلمة package أي رزمة أو حزمة من الأصناف و هنا ما يحدث أنك تستطيع أن تستخد أي دالة أو متغير يحملون المحدد من نوع protected فقط أن كانو بنفس الpackage أما خارجها فسيطبع لك خطأ كالتالي : // الرزمة التي تحتوي على الصنفين package p1; // الصنف الأول public class Demo1 { // الدالة الأولى private void show() { System.out.println("Javatpoint"); } } // الصنف الثاني و ينتمي لنفس الرزمة public class Demo2 { // الدالة الثانية تستخدم الدالة الأولى للطباعة public void show2() { Demo1 obj = new Demo1(); obj.show(); } } // أما أن أستخدمتها مبتشرة داخل ال main فسيعطيك خطأ
- 3 اجابة
-
- 1
-
العبرة ليست في الحل العبرة هل انت على دراية كيف تقومين بكتابة صنف و دالة لأن باقي الدوال عبارة عن مجرد عمليات حسابية إن كان تلك المشكلة فسأقوم بشرح الصنف و كيفية كتابته و الدالة و كيف يتم كتابتها
-
يبدو أن هنالك أوبجكت أخر يقوم بتعديل الحالة بعد أن زال المكون Component يمكنك أن تحاول بطريقة بسيطة عمل فحص لحالة المكون أن كان مثبت mount و أن كان المكون مثبت فقم بعمل بتحديث الحالة و أن لم يكن فلا تقم بتغيير الحالة كالتالي: if (!this.mounted) return; setState(){ /** **/ }
- 6 اجابة
-
- 1
-
يقوم Double Pre Underscores بإخبار مترجم Python بإعادة كتابة اسم السمة للفئات الفرعية لتجنب تعارض التسمية. Name Mangling: - يقوم مترجم Python بتغيير اسم المتغير بطريقة تجعل من الصعب الصدام عندما يتم توريث الفئة. بما معناه أن البايثون يقوم بتغيير الأسم حتى لا يكون هناك اي تصادمات بين اسماء المتغيرات الموجود فحتى لو حاولت أستخدام اوبجت من الصنف ثم قمت بإستخدام أسم هذا المتغير حتى تقوم بتغييره أو طباعته فلن يكون موجود على الإطلاق لانه تم تغيير أسم المتغير بهذه الطريقة class Sample(): def __init__(self): self.a = 1 self._b = 2 self.__c = 3 obj1 = Sample() dir(obj1) فلن يقوم بطباعة الخاصية __c أما أن أردت طباعتها قستقوم بالتتالي print(obj1._Sample__c) تعمل هذه الحاصية حتى يتم التفريق بين المتغيرات و خصوصا بالتوريت فأذا اردت أستخدام نفس أسم المتغير في الأصناف التي يتم توريثها من صنف آخر فما عليك سوي وضع هاتين الشرطتين و هنا سأقوم بوضع مثال على التوريث كالتالي class Sample(): def __init__(self): self.a = 1 self._b = 2 self.__c = 3 #هنا صنف ثاني يرث من الصنف الأول class SecondClass(Sample): def __init__(self): super().__init__() self.a = "overridden" self._b = "overridden" self.__c = "overridden" obj2 = SecondClass() print(obj2.a) #سيقوم بطباعة override print(obj2._b) #سيقوم بطباعة override print(obj2.__c)# سيقوم بإعطاء أنه لا يوجد متغير بهذا الأسم # لكن هنا يمكنك أن تستخدم المنغير للصنف الأول و الثاني أيضا بهذا الطريقة print(obj2._SecondClass__c) #سيطبع overridden print(obj2._Sample__c) # سيطبع 3
- 2 اجابة
-
- 2
-
من خلال التيرمنل أكتب code -v
-
ما هو الأصدار الخاص بال VS CODE ؟ حيث أنه يجب أن يكون الVS CODE 17 على الأقل لحل هذه المشكلة