विषयसूची एक टेम्पलेट का उपयोग कर रेपो प्रारंभ करें एक टेम्पलेट की प्रारंभिक संरचना टेम्पलेट से स्क्रिप्ट का उपयोग करके नियम जोड़ना एस्लिंट प्लगइन के लिए परीक्षण लिखें एस्लिंट नियम लिखिए लघु एएसटी स्पष्टीकरण अंतिम संस्करण स्क्रिप्ट का उपयोग करके दस्तावेज़ों को अपडेट करना प्लगइन प्रकाशन इसे अपने एप्लिकेशन से कनेक्ट करें पृष्ठभूमि मैं चरण-दर-चरण स्पष्टीकरण के साथ रीटॉम रिपॉजिटरी में अपने पीआर के आधार पर एक ट्यूटोरियल लिखने की कोशिश करूंगा: https://github.com/artalar/Reatom/pull/488 यदि आप अधिक जानना चाहते हैं, तो आप इस मुद्दे को https://github.com/artalar/reatom/issues/487 पढ़ सकते हैं। थोड़ा संदर्भ जोड़ने के लिए, रीटॉम एक राज्य प्रबंधन पुस्तकालय है। रिएक्ट के लिए एक राज्य प्रबंधन पुस्तकालय, रीटॉम में परमाणु एक अवधारणा है। ESLint प्लगइन्स और नियम क्या हैं? ESLint प्लगइन्स एक्सटेंशन हैं जो विशिष्ट कोडिंग मानकों को लागू करने के लिए कोर ESLint पैकेज के साथ काम करते हैं। प्लगइन्स में एक फ़ोल्डर होता है, जो इन मानकों को लागू करने के लिए अलग-अलग नियमों को परिभाषित करता है। rules प्रत्येक मॉड्यूल में एक गुण होता है जो वर्णन करता है और एक गुण होता है जो व्यवहार को परिभाषित करता है। rule meta नियम का create नियम के फ़ंक्शन एक तर्क लेता है, जिसका उपयोग चेक किए जा रहे कोड के साथ इंटरैक्ट करने के लिए किया जाता है, और आप इसका उपयोग अपने नियम के तर्क को परिभाषित करने के लिए कर सकते हैं, जैसे आपकी लाइब्रेरी के लिए सख्त नामकरण सम्मेलनों की आवश्यकता होती है। create context आइए कोड में गोता लगाएँ रेपो को इनिशियलाइज़ करें एक नया टाइपस्क्रिप्ट एस्लिंट प्रोजेक्ट बनाना npx degit https://github.com/pivaszbs/typescript-template-eslint-plugin reatom-eslint-plugin फिर, नई परियोजना निर्देशिका पर जाएँ, और इसके साथ निर्भरताएँ स्थापित करें: cd reatom-eslint-plugin && npm i मैं एक अच्छा लड़का बनना चाहता हूं, इसलिए मैं गिट में प्रवेश करता हूं। git init && git add . && git commit -m "init" अगला, फ़ाइल खोलें, और फ़ील्ड खोजें। यह फ़ील्ड आवश्यक है क्योंकि जब इसका उपयोग किया जाएगा तो यह आपके प्लगइन के लिए मुख्य प्रवेश बिंदु होगा। आप इसे निम्न में बदल सकते हैं: package.json name "name": "eslint-plugin-reatom" वैकल्पिक रूप से, आप स्कोप्ड पैकेज नामकरण सम्मेलन का उपयोग कर सकते हैं: "name": "@reatom/eslint-plugin" प्रारंभिक संरचना - scripts // some automation to concentrate on writing rules - docs - rules // here will be generated by npm run add-rule files - src - configs recommended.ts // generated config - rules // all your rules index.ts // Connection point to your plugin, autogenerated by scripts/lib/update-lib-index.ts 😀 सामान्य अनुक्रमणिका में, फ़ाइलें स्क्रिप्ट द्वारा उत्पन्न की जाएंगी, इसलिए आपको इसके बारे में चिंता करने की आवश्यकता नहीं है /* DON'T EDIT THIS FILE. This is generated by 'scripts/lib/update-lib-index.ts' */ import { recommended } from './configs/recommended'; import exampleRule from './rules/example-rule' export const configs = { recommended }; export const rules = { 'example-rule': exampleRule }; नियम जोड़ना और डॉक्स अपडेट करना इस रिपॉजिटरी में, आपको नियम जोड़ने और दस्तावेजों को अपडेट करने के लिए कुछ सुविधाजनक स्क्रिप्ट्स मिलेंगी। नया नियम जोड़ने के लिए, आप निम्न आदेश का उपयोग कर सकते हैं: npm run add-rule atom-rule suggestion यह नए नियम के लिए तीन खंड उत्पन्न करेगा: प्रलेखन, परीक्षण और वास्तविक कोड। हम अभी के लिए प्रलेखन अनुभाग को छोड़ सकते हैं और अंतिम दो पर ध्यान केंद्रित कर सकते हैं। टेस्ट लिखें TDD (परीक्षण-संचालित विकास) उत्साही के रूप में, हम फ़ाइल में कुछ सरल परीक्षण बनाकर शुरू करेंगे: tests/atom-rule.ts // tests/atom-rule.ts tester.run('atom-rule', atomRule, { valid: [ { code: 'const countAtom = atom(0, "countAtom");' }, ], invalid: [ { code: `const countAtom = atom(0);`, errors: [{ message: 'atom name is not defined' }] }, { code: 'const countAtom = atom(0, "count");', errors: [{ message: 'atom name is defined bad'}] }, ] }); यदि आप अभी परीक्षण चलाते हैं, तो वे विफल हो जाएँगे क्योंकि हमने अभी तक लागू नहीं किया है। atomRule नियम लिखना वह जगह है जहाँ हम नियम के व्यवहार को परिभाषित करते हैं। यहाँ एक सरल कार्यान्वयन है: atomRule import { Rule } from "eslint"; const rule: Rule.RuleModule = { meta: { docs: { description: "Add name for every atom call", // simply describe your rule recommended: true, // if it's recommended, then npm run update will add it to recommmended config }, type: "suggestion" }, create: function (context: Rule.RuleContext): Rule.RuleListener { return { VariableDeclaration: node => { // listener for declaration, here we can specifiy more specific selector node.declarations.forEach(d => { if (d.init?.type !== 'CallExpression') return; if (d.init.callee.type !== 'Identifier') return; if (d.init.callee.name !== 'atom') return; if (d.id.type !== 'Identifier') return; // just guard everything that we don't need if (d.init.arguments.length <= 1) { // show error in user code context.report({ message: `atom name is not defined`, // here we can pass what will be underlined by red/yellow line node, }) } if (d.init.arguments[1]?.type !== 'Literal') return; // just another guard if (d.init.arguments[1].value !== d.id.name) { context.report({ message: `atom name is defined bad`, node }) } }) } }; }, }; export default rule; यह एक साधारण प्रकार है, लेकिन यहाँ, हम आसानी से समझ सकते हैं कि क्या हो रहा है। अपने कोड की एएसटी संरचना की बेहतर समझ के लिए, आप या केवल कंसोल.लॉग पार्स किए गए नोड्स का उपयोग कर सकते हैं। https://astexplorer.net/ एएसटी टाइपिंग की बेहतर समझ के लिए एक छोटा सा स्पष्टीकरण यहाँ एक छोटे से उदाहरण में प्रत्येक पहचानकर्ता का एक छोटा सा विवरण दिया गया है: const kek = atom('kek') : एक टाइपस्क्रिप्ट इंटरफ़ेस जो एएसटी में एक पहचानकर्ता नोड का प्रतिनिधित्व करता है। Identifier const = ('kek'), और पहचानकर्ता नोड हैं। kek atom केक, परमाणु : एक टाइपस्क्रिप्ट इंटरफ़ेस जो एएसटी में एक शाब्दिक मान (स्ट्रिंग, संख्या, बूलियन, आदि) नोड का प्रतिनिधित्व करता है। const kek = atom(' '), 'kek' एक Literal kek शाब्दिक है। : एक टाइपस्क्रिप्ट इंटरफ़ेस जो एक सार सिंटैक्स ट्री (एएसटी) में फ़ंक्शन कॉल एक्सप्रेशन नोड का प्रतिनिधित्व करता है। CallExpression हमारे उदाहरण में, एक कॉलएक्सप्रेशन है, जिसमें atom('kek') परमाणु-पहचानकर्ता और केक-शाब्दिक होते हैं। : एक टाइपस्क्रिप्ट इंटरफ़ेस जो एएसटी में एक वेरिएबल डिक्लेरेटर नोड का प्रतिनिधित्व करता है VariableDeclarator हमारे उदाहरण में, const को छोड़कर संपूर्ण व्यंजक VariableDeclarator है kek = atom('kek') : एक टाइपस्क्रिप्ट इंटरफ़ेस जो एक सामान्य एएसटी नोड का प्रतिनिधित्व करता है। Node या बस एस्टएक्सप्लोरर का उपयोग करना https://astexplorer.net/?embedable=true#/gist/7fe145026f1b15adefeb307427210d38/35f114eb5b9c4d3cb626e76aa6af7782927315ed अंतिम संस्करण अंतिम परीक्षण tester.run('atom-rule', rule, { valid: [ { code: ` import { atom } from '@reatom/framework' const countAtom = atom(0, "countAtom"); ` }, { code: `const countAtom = atom(0);`, }, { code: 'const countAtom = atom(0, "count");', }, ], invalid: [ { code: ` import { atom } from '@reatom/framework' const countAtom = atom(0); `, errors: [{ message: 'atom "countAtom" should has a name inside atom() call', }], output: ` import { atom } from '@reatom/framework' const countAtom = atom(0, "countAtom"); `, }, { code: ` import { atom } from '@reatom/framework' const countAtom = atom(0, "count"); `, errors: [{ message: `atom "countAtom" should be named as it's variable name, rename it to "countAtom"` }], output: ` import { atom } from '@reatom/framework' const countAtom = atom(0, "countAtom"); `, }, ] }); परीक्षणों से, हम समझते हैं कि हमें अपने नियम का उपयोग करके स्रोत कोड को किसी तरह बदलने की आवश्यकता है। अपने नियम को कैसे ठीक करें? संदर्भ रिपोर्ट में एक सरल रेखा जोड़ें। fix: fixer => fixer.replaceText(node, replaceString) - एक वास्तविक नोड या प्रतीकों की श्रेणी हो सकती है जिसे आप बदलना चाहते हैं। नोड - आप किस कोड को देखने की उम्मीद करते हैं। replaceString अपने नियम मेटा टैग के लिए : 'कोड' या : 'व्हाट्सएप' जोड़ना न भूलें। फिक्सेबल फिक्सेबल यदि आप इसे एस्लिंट से ठीक करने के तरीके से परिचित नहीं हैं, तो बस अपने मौजूदा प्रोजेक्ट पर प्रयास करें। eslint --fix ./src कोड स्वयं import { Rule } from "eslint"; import { CallExpression, Identifier, Literal, VariableDeclarator, Node } from 'estree'; import { isIdentifier, isLiteral } from "../lib"; type AtomCallExpression = CallExpression & { callee: Identifier, arguments: [Literal] | [Literal, Literal] } type AtomVariableDeclarator = VariableDeclarator & { id: Identifier, init: AtomCallExpression } const noname = (atomName: string) => `atom "${atomName}" should has a name inside atom() call`; const invalidName = (atomName: string) => `atom "${atomName}" should be named as it's variable name, rename it to "${atomName}"`; export const atomRule: Rule.RuleModule = { meta: { type: 'suggestion', docs: { recommended: true, description: "Add name for every atom call" }, fixable: 'code' }, create: function (context: Rule.RuleContext): Rule.RuleListener { let importedFromReatom = false; return { ImportSpecifier(node) { const imported = node.imported.name; // @ts-ignore const from = node.parent.source.value; if (from.startsWith('@reatom') && imported === 'atom') { importedFromReatom = true; } }, VariableDeclarator: d => { if (!isAtomVariableDeclarator(d) || !importedFromReatom) return; if (d.init.arguments.length === 1) { reportUndefinedAtomName(context, d); } else if (isLiteral(d.init.arguments[1]) && d.init.arguments[1].value !== d.id.name) { reportBadAtomName(context, d); } } }; } } function isAtomCallExpression(node?: Node | null): node is AtomCallExpression { return node?.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'atom'; } function isAtomVariableDeclarator(node: VariableDeclarator): node is AtomVariableDeclarator { return isAtomCallExpression(node.init) && isIdentifier(node.id); } function reportUndefinedAtomName(context: Rule.RuleContext, d: AtomVariableDeclarator) { context.report({ message: noname(d.id.name), node: d, fix: fixer => fixer.insertTextAfter(d.init.arguments[0], `, "${d.id.name}"`) }); } function reportBadAtomName(context: Rule.RuleContext, d: AtomVariableDeclarator) { context.report({ message: invalidName(d.id.name), node: d, fix: fixer => fixer.replaceText(d.init.arguments[1], `"${d.id.name}"`) }); } जैसा कि आप देख सकते हैं, इसमें केवल बेहतर त्रुटियाँ हैं, गार्ड टाइप करें, और आयात जाँच शामिल है। और, ज़ाहिर है, मैं नियम को ठीक करने योग्य बनाता हूँ। डॉक्स को अपडेट कर रहा है दस्तावेज़ों को अद्यतन करने के लिए, आप निम्न आदेश का उपयोग कर सकते हैं: npm run update यह आदेश प्रत्येक नियम के लिए README.md और अद्यतन दस्तावेज़ अपडेट करेगा (लेकिन आपको दस्तावेज़/{नियम} फ़ाइल में प्रत्येक नियम के बारे में कुछ लिखने की आवश्यकता है)। साथ ही, जैसा कि मैंने कहा, आपको अनुक्रमणिका फ़ाइल के बारे में चिंता करने की आवश्यकता नहीं है। चरण प्रकाशित करें सुनिश्चित करें कि संस्करण आपके package.json में है। "version": "1.0.0" अगर यह 1.0.0 नहीं है तो टर्म में लिखें। npm version 1.0.0 तो बस जड़ में लिखो। npm publish सब कुछ आपके परिभाषित पैकेज नाम के साथ बनाया और प्रकाशित किया जाएगा। इसे अपने एप्लिकेशन से कनेक्ट करें मैं अपने पैकेज का नाम देता हूं। @reatom/eslint-plugin तो, मुझे इसे स्थापित करने की ज़रूरत है। npm i @reatom/eslint-plugin और मेरे .eslintrc कॉन्फ़िग में जोड़ें। module.exports = { plugins: [ "@reatom" ], // use all rules extends: [ "plugin:@reatom/recommended" ], // or pick some rules: { '@reatom/atom-rule': 'error', // aditional rules, you can see it in PR '@reatom/action-rule': 'error', '@reatom/reatom-prefix-rule': 'error' } } और सब कुछ बस काम करता है (सिर्फ के लिए आपको हर जगह के बजाय " लिखना चाहिए)। reatom-eslint-plugin “@reatom" “reatom” निष्कर्ष इस ट्यूटोरियल में, हमने रीटॉम स्टेट मैनेजमेंट लाइब्रेरी के लिए ESLint प्लगइन बनाने की प्रक्रिया के बारे में जाना। हम कवर करते हैं: टाइपस्क्रिप्ट में एस्लिंट प्लगइन कैसे लिखें। इसे टेस्ट से कैसे कवर करें। इसे --fix विकल्प के साथ कैसे काम करें। मेरे टेम्पलेट का उपयोग कैसे करें। एस्लिंट प्लगइन को कैसे प्रकाशित करें। एस्लिंट के साथ इसे अपने मौजूदा रिपॉजिटरी में कैसे जोड़ें आगे सीखने और अन्वेषण के लिए संसाधन https://github.com/pivaszbs/typescript-template-eslint-plugin https://astexplorer.net/ https://github.com/artalar/reatom/pull/488/files https://eslint.org/docs/latest/extend/plugins https://www.reatom.dev/ https://github.com/artalar/reatom https://docs.npmjs.com/about-semantic-versioning मस्ती करो :)