ESLint
eslint-plugin-textjs: کونسول کے لیے محفوظ JSX، سیل کی چوڑائی والے گلفس، فریم کی رفتار والے ٹائمرز اور App Router کی جانچ۔
eslint-plugin-textjs ایڈیٹر میں Text.js کی غلطیاں پکڑتا ہے: کونسول کمپوننٹس میں DOM ٹیگز، متن کے اندر باکس، ایسے گلف جو Menlo میں نہیں ہیں، غیر ضروری console.log کالز اور App Router کے ایسے ایکسپورٹس جنہیں خاموشی سے نظر انداز کر دیا جاتا ہے۔
سیٹ اپ
bun add -d eslint eslint-plugin-textjs typescript-eslintimport { defineConfig } from "eslint/config";import tseslint from "typescript-eslint";import textjs from "eslint-plugin-textjs";export default defineConfig(tseslint.configs.recommended, textjs.configs.recommended);پلگ ان فلیٹ کنفگ کے ساتھ ESLint 9 اور 10 کو سپورٹ کرتا ہے۔ قواعد نحوی ہیں اور انہیں ٹائپ کی معلومات یا parserOptions.project کی ضرورت نہیں ہے۔ TypeScript اور JSX کو سمجھنے والا کوئی بھی پارسر کام کرتا ہے۔
کنفگز
| کنفگ | فعال ہونے والے قواعد |
|---|---|
textjs.configs.recommended | درستگی کا ہر قاعدہ بطور ایرر؛ کونسول، ٹائمر اور فریم کی رفتار کے قواعد بطور وارننگ |
textjs.configs.strict | سب کچھ بطور ایرر، ساتھ میں prefer-use-keymap بطور وارننگ |
اس کے بجائے قواعد الگ الگ منتخب کریں:
import textjs from "eslint-plugin-textjs";export default [ { plugins: { textjs }, rules: { "textjs/no-box-in-text": "error", "textjs/no-console-in-components": ["warn", { allow: ["error"], logger: "log" }], }, },];کونسول فائلیں
زیادہ تر قواعد صرف ان فائلوں پر لاگو ہوتے ہیں جو کونسول میں رینڈر کرتی ہیں: ایسی فائلیں جو @textjs/app یا @textjs/react سے کوئی کمپوننٹ یا ہک (Box، Text، useInput، …) امپورٹ کرتی ہیں۔ react-dom یا @textjs/react/dom امپورٹ کرنے والی فائلیں صفحے کا کوڈ ہیں اور انہیں نہیں چھیڑا جاتا، اس لیے ویب سائٹ ایک ہی پروجیکٹ میں DOM صفحات اور کونسول ایپس رکھ سکتی ہے۔ tokenize یا parseMarkdown جیسی یوٹیلیٹی امپورٹ کرنے سے فائل کونسول فائل نہیں بنتی۔
import textjs from "eslint-plugin-textjs";export default [ textjs.configs.recommended, { settings: { textjs: { packages: ["@acme/console-ui"], // also re-exports Text.js components consoleFiles: "imports", // or "all" }, }, },];App Router کے قواعد کسی بھی app/ ڈائریکٹری میں فائل کے نام (page.tsx، layout.tsx، route.ts، …) کے مطابق چلتے ہیں، جس میں src/app/ بھی شامل ہے۔ اگر آپ کی ڈائریکٹری کا نام کچھ اور ہے تو valid-route-module، valid-metadata اور route-handler-exports کو { appDir: "routes" } دیں۔
قواعد
| قاعدہ | تجویز کردہ | اصلاح |
|---|---|---|
no-dom-elements | ایرر | تجویز |
no-box-in-text | ایرر | |
no-unsupported-glyphs | ایرر | خودکار اصلاح، تجویز |
no-console-in-components | وارننگ | تجویز |
prefer-use-interval | وارننگ | تجویز |
no-sub-frame-timers | وارننگ | |
prefer-use-keymap | صرف strict | |
valid-route-module | ایرر | |
valid-metadata | ایرر | |
route-handler-exports | ایرر | تجویز |
no-dom-elements
<div>، <span>، کسٹم ایلیمنٹس اور دیگر DOM ٹیگز کونسول میں موجود نہیں ہیں۔ ریکنسائلر صرف اپنے ہوسٹ نوڈز کو پہچانتا ہے اور کسی بھی دوسری چیز پر TX003 ایرر دیتا ہے۔
<div className="flex-col"> // ✗<Box className="flex-col"> // ✓<strong>Deployed</strong> // ✗<Text bold>Deployed</Text> // ✓تجویز ٹیگ کو قریب ترین کمپوننٹ (div → Box، span/p → Text، strong → Text bold، a → Link، input → Input، hr → Divider، …) سے بدلتی ہے اور امپورٹ شامل کرتی ہے۔
no-box-in-text
<Text> اسٹائل والے spans کا سلسلہ ہے؛ اس کے اندر باکس نہیں ہو سکتا۔ <Box> یا باکس روٹ والے کسی کمپوننٹ (<ScrollBox>، <Input>، <Code>، <ProgressBar>، <Divider>، …) کو اندر رکھنے سے رینڈر کے وقت TX004 ایرر آتا ہے۔ یہ قاعدہ اسے ایڈیٹر ہی میں پکڑ لیتا ہے، بشمول &&، ٹرنری ایکسپریشنز، فریگمنٹس اور .map() کے اندر۔
<Text>Status <Box /></Text> // ✗<Box className="flex-row gap-1"><Text>Status</Text><Box /></Box> // ✓<Text>Press <Kbd>⌘K</Kbd> <Spinner /></Text> // ✓ inline componentsno-unsupported-glyphs
Text.js ہر حرف کو مقررہ سیل گرڈ میں ترتیب دیتا ہے۔ جو گلف macOS پر DevTools کونسول کے فونٹ Menlo میں نہیں ہیں، وہ فال بیک فونٹ میں رینڈر ہوتے ہیں جو سیل سے چوڑا ہوتا ہے، اس لیے ان کے بعد ہر سیل اپنی جگہ سے ہٹ جاتا ہے۔
- بریل (U+2800–U+28FF، ٹرمینل کے روایتی اسپنر فریم): بلاک یا کواڈرنٹ حروف (
▘▝▗▖)،<Spinner variant="dots">یا چارٹس پرmarker="quadrant"استعمال کریں۔ صرف ٹرمینل میںtext runسے چلنے والی ایپس کے لیے{ allowBraille: true }سیٹ کریں۔ - متفرق علامات اور تیر (U+2B00–U+2BFF، جیسے چھوٹا مربع U+2B1D): تجاویز Menlo کے متبادل (
·،●،←) پیش کرتی ہیں۔ - ایک سیل کی علامات کی ایموجی شکل (
▶یا↩کے بعد U+FE0F): ویری ایشن سلیکٹر انہیں دو سیل کے ایموجی میں بدل دیتا ہے جبکہ گرڈ ایک سیل محفوظ رکھتا ہے۔ خودکار اصلاح اسے ہٹا دیتی ہے۔
چوڑے ایموجی (🚀، ✅) درست ہیں: Text.js انہیں دو سیل کے طور پر ماپتا ہے۔
no-console-in-components
ہر فریم ایک console.log ہے۔ آپ کے اپنے لاگز فریموں کے درمیان آتے ہیں، اگلا فریم انہیں اسکرول کرکے ہٹا دیتا ہے اور وہ نیچے چپکے رہنے والے ویو میں چھپ جاتے ہیں۔ console.clear() خود ایپ کو مٹا دیتا ہے۔
"textjs/no-console-in-components": ["warn", { allow: ["error"], logger: "log" }]UI میں پیغامات دکھانے کے لیے useToast() یا لاگ <ScrollBox> استعمال کریں، یا [▼] Dev Overlay (Ctrl+`) میں اسٹیٹ کا معائنہ کریں۔ logger کے ساتھ، تجویز console.warn(…) کو log.warn(…) میں بدلتی ہے۔ ٹیسٹ فائلوں اور @textjs/app/testing رینڈرز کو چھوڑ دیا جاتا ہے۔
prefer-use-interval
کمپوننٹ میں براہ راست setInterval استعمال کرنے پر پرانی اسٹیٹ سے بچنے کے لیے ایک افیکٹ، ایک کلین اپ اور ایک ریف درکار ہوتا ہے۔ useInterval تینوں کام کرتا ہے، اور null اسے روک دیتا ہے۔
useEffect(() => { if (paused) return; const id = setInterval(tick, 1000); return () => clearInterval(id);}, [paused]);useInterval(tick, paused ? null : 1000); // the suggestionاینیمیشن کے لیے، useAnimationFrame رینڈرر کی فریم رفتار کی پیروی کرتا ہے اور آؤٹ پٹ موقوف ہونے پر رک جاتا ہے۔ یوٹیلیٹی ہکس دیکھیں۔
no-sub-frame-timers
Text.js ہر 66 ms میں زیادہ سے زیادہ ایک فریم خارج کرتا ہے (تقریباً 15 fps)۔ 16 ms کا وقفہ ہر خارج شدہ فریم پر چار بار رینڈر کرتا ہے؛ اضافی فریم یکجا ہو جاتے ہیں اور صرف CPU استعمال کرتے ہیں۔ یہ minInterval (ڈیفالٹ 66) سے کم setInterval/useInterval تاخیر اور 15 سے زیادہ fps والے useAnimationFrame کی نشاندہی کرتا ہے۔
prefer-use-keymap
e.key کا دستی موازنہ کام کرتا ہے، لیکن شارٹ کٹس نظر نہیں آتے۔ useKeymap لیبل والی بائنڈنگز کو <KeyHelp>، <KeyHints> (hint: true والی بائنڈنگز) اور کمانڈ پیلیٹ میں رکھتا ہے، g g جیسے سلسلے سنبھالتا ہے اور میچ ہونے والی کیز کی پروپیگیشن روک دیتا ہے۔ یہ ان useInput ہینڈلرز کی نشاندہی کرتا ہے جو دو یا زیادہ کی لٹرلز (minKeys) کا موازنہ کرتے ہیں اور ٹائپنگ کے لیے e.input پڑھنے والے ہینڈلرز کو چھوڑ دیتا ہے۔
useKeymap({ "up, k": { label: "Increment", run: inc, hint: true }, "down, j": { label: "Decrement", run: dec, hint: true },});کی بورڈ شارٹ کٹس دیکھیں۔
valid-route-module
page،layout،loading،errorاورnot-foundفائلوں کو ایک کمپوننٹ بطور ڈیفالٹ ایکسپورٹ کرنا ضروری ہے (TX015)۔export const dynamicلازماً"auto"،"force-static"یا"force-dynamic"ہونا چاہیے (TX031)۔ Text.js، Next.js کے"error"کو سپورٹ نہیں کرتا۔ اسے صفحات، لے آؤٹس اور روٹ ہینڈلرز سے پڑھا جاتا ہے۔ صفحات اور لے آؤٹس میں اسے سادہ اسٹرنگ لٹرل کے طور پر لکھیں:text buildماڈیول چلائے بغیر اسے سورس سے پڑھتا ہے۔
valid-metadata
Metadata پہلے لے آؤٹس سے، پھر صفحے (یا not-found) سے مرج ہوتا ہے۔ یہ قاعدہ ان چیزوں کی نشاندہی کرتا ہے جنہیں راؤٹر خاموشی سے نظر انداز کر دیتا:
loadingیاerrorفائلوں میںmetadataیاgenerateMetadata- ایک فائل میں دونوں ایکسپورٹس
async generateMetadata: اسے سنکرونس طور پر کال کیا جاتا ہے، اس لیے Promise کبھی عنوان سیٹ نہیں کرتا- ایسا
titleجو اسٹرنگ یا{ default, template?, absolute? }نہ ہو، یا غلط ہجے والی کی %sکے بغیرtitle.template، یا صفحے میں اس کا استعمال، جہاں اس کا کوئی اثر نہیں ہوتا- غیر اسٹرنگ
description
route-handler-exports
route.ts فائلیں صرف ان HTTP میتھڈز کا جواب دیتی ہیں جنہیں وہ ایکسپورٹ کرتی ہیں: GET، HEAD، POST، PUT، PATCH، DELETE اور OPTIONS۔ چھوٹے حروف والا get یا Post کبھی کال نہیں ہوتا (درخواستوں کو 405 ملتا ہے)؛ تجویز اس کا نام بدل دیتی ہے۔ ڈیفالٹ ایکسپورٹس، نان فنکشن ہینڈلرز اور دیگر ایکسپورٹس کی نشاندہی ہوتی ہے، سوائے dynamic اور revalidate روٹ سیگمنٹ کنفگ کے۔ مشترکہ کوڈ lib/ میں منتقل کریں، یا { allow: [...] } کے ساتھ اضافی نام درج کریں۔
export function get() { … } // ✗ never calledexport function GET() { … } // ✓