欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

TypeScript手寫一個(gè)簡(jiǎn)單的eslint插件實(shí)例

 更新時(shí)間:2023年02月06日 09:50:59   作者:hans774882968  
這篇文章主要為大家介紹了TypeScript手寫一個(gè)簡(jiǎn)單的eslint插件實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

看到參考鏈接1以后,覺得用TS寫一個(gè)eslint插件應(yīng)該很簡(jiǎn)單??????,嘗試下來確實(shí)如此。

前置知識(shí)

本文假設(shè)

  • 你對(duì)AST遍歷有所了解。
  • 你寫過單測(cè)用例。

第一個(gè)eslint規(guī)則:no-console

為了簡(jiǎn)單,我們只使用tsc進(jìn)行構(gòu)建。首先package.json需要設(shè)置入口"main": "dist/index.js",,tsconfig.json需要設(shè)置"outDir": "dist""include": ["src"]。接下來設(shè)計(jì)一下單元測(cè)試和構(gòu)建命令:

"scripts": {
  "clean": "rm -Rf ./dist/",
  "build": "yarn clean && mkdir ./dist && tsc",
  "test": "jest",
  "test:help": "jest --help",
  "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\" \"test/**/*.{js,jsx,ts,tsx}\" \"*.{js,jsx,ts,tsx}\" --fix"
},

ESLintUtils.RuleTester寫的.test.tsmocha或者jest都能運(yùn)行,我選擇了jest

當(dāng)我們運(yùn)行yarn lint時(shí),node_modules/@eslint/eslintrc/lib/config-array-factory.jsthis._loadPlugin會(huì)加載插件,相當(dāng)于在node環(huán)境運(yùn)行上面指定的入口點(diǎn)dist/index.js。所以我們需要知道@eslint如何描述一個(gè)eslint插件,才能寫出src/index.ts。查看this._loadPlugin可知,plugin.definition的類型應(yīng)為:

type Plugin = {
  configs?: Record<string, ConfigData> | undefined;
  environments?: Record<string, Environment> | undefined;
  processors?: Record<string, Processor> | undefined;
  rules?: Record<...> | undefined;
}

結(jié)合參考鏈接1,我們得出結(jié)論:一般來說需要提供rulesconfigs屬性。rules可以理解為具體的規(guī)則定義;configs可以理解為規(guī)則的集合,可以稱為“最佳實(shí)踐”,最常見的configsrecommended。

于是寫出src/index.ts

import rules from './rules';
import configs from './configs';
const configuration = {
  rules,
  configs
};
export = configuration;

src/rules/index.ts

import noConsole from './noConsole';
const allRules = {
  'no-console': noConsole
};
export default allRules;

src/configs/index.ts

import all from './all';
import recommended from './recommended';
const allConfigs = {
  all,
  recommended
};
export default allConfigs;

src/configs/all.ts

export default {
  parser: '@typescript-eslint/parser',
  parserOptions: { sourceType: 'module' },
  rules: {
    '@hans/use-i18n-hans/no-console': 'error'
  }
};

我們用createRule函數(shù)來創(chuàng)建一條規(guī)則。它需要傳一個(gè)對(duì)象,我列舉一下這個(gè)對(duì)象常用的幾個(gè)屬性:

  • meta.schema:配置eslint規(guī)則的時(shí)候可以指定的options參數(shù)。通常傳入的值為{}(不接收參數(shù))和object[]。
  • meta.messages:一個(gè)對(duì)象,{ messageId: text }。
  • create方法:eslint需要建立AST并遍歷,所以要拿到這個(gè)方法的返回值作為遍歷AST的配置。輸入?yún)?shù)是context對(duì)象,常用的方法有:context.options[0]獲取傳入的參數(shù);context.getFilename()獲取當(dāng)前yarn lint正在解析的文件名;context.report函數(shù)向用戶報(bào)錯(cuò),通常這么用:context.report({ node, messageId: 'xxMessageId' }),messageId必須符合meta.messages給出的定義。create方法返回的對(duì)象有點(diǎn)類似于@babel/traversetraverse方法的第二個(gè)參數(shù),具體寫法看參考鏈接1的項(xiàng)目就行。
import { TSESLint, ASTUtils } from '@typescript-eslint/utils';
import createRule from '../utils/createRule';
import path from 'path';
import multimatch from 'multimatch';
// 模仿babel中的寫法 import { isIdentifier } from '@babel/types';
const {
  isIdentifier
} = ASTUtils;
const whiteList = ['memory'];
const rule = createRule({
  name: 'no-console',
  meta: {
    docs: {
      description: 'Remember to delete console.method()',
      recommended: 'error',
      requiresTypeChecking: false
    },
    messages: {
      rememberToDelete: 'Remember to delete console.method()'
    },
    type: 'problem',
    schema: {}
  },
  create (
    context: Readonly<TSESLint.RuleContext<'rememberToDelete', never[]>>
  ) {
    return {
      MemberExpression (node) {
        if (isIdentifier(node.object) && node.object.name === 'console' &&
            isIdentifier(node.property) && Object.prototype.hasOwnProperty.call(console, node.property.name) &&
            !whiteList.includes(node.property.name)
        ) {
          context.report({ node, messageId: 'rememberToDelete' });
        }
      }
    };
  }
});
export default rule;

代碼傳送門:src/rules/noConsole.ts

本地測(cè)試

單元測(cè)試:

yarn test

本地查看效果

首先:

yarn build

在另一個(gè)項(xiàng)目(這里用了相對(duì)路徑,用絕對(duì)路徑也行):

yarn add -D file:../eslint-plugin-use-i18n-hans

注意:每次重新build后都需要在另一個(gè)項(xiàng)目重新yarn add

這樣會(huì)得到:

{
  "devDependencies": {
    "@hans/eslint-plugin-use-i18n-hans": "file:../eslint-plugin-use-i18n-hans",
  }
}

接下來配置.eslintrc.js

module.exports = {
  plugins: [
    '@hans/use-i18n-hans',
  ],
  extends: [
    'plugin:@hans/use-i18n-hans/recommended',
  ],
}

插件名為@hans/use-i18n-hans,使用了configs中的recommended

最后重啟vscode或運(yùn)行yarn lint就能看到我們的第一個(gè)eslint插件生效了。

<path>/file-encrypt/webpack-plugin-utils.js
  16:5  error  Remember to delete console.log()  @hans/use-i18n-hans/no-console

no-console規(guī)則添加功能:排除用戶指定的文件

修改一下meta.schema,新增輸入?yún)?shù):

schema = [
  {
    properties: {
      excludedFiles: {
        type: 'array'
      }
    }
  }
]

和對(duì)應(yīng)的類型定義:

type Options = [{
  excludedFiles: string[];
}];
{
  create (
    context: Readonly<TSESLint.RuleContext<'rememberToDelete', Options>>
  ) {}
}

然后在create函數(shù)體加幾句判定:

const fileName = context.getFilename();
const options = context.options[0] || {};
const { excludedFiles } = options;
if (Array.isArray(excludedFiles)) {
  const excludedFilePaths = excludedFiles.map(excludedFile => path.resolve(excludedFile));
  if (multimatch([fileName], excludedFilePaths).length > 0) {
    return {};
  }
}

context.getFilename()文檔:eslint.org/docs/latest… 。其特性:在yarn test時(shí)會(huì)返回file.ts,在作為npm包引入另一個(gè)項(xiàng)目后,可以正常獲取文件的絕對(duì)路徑。

為了支持glob語法,我們引入了multimatch。但需要指定版本為5.0.0,因?yàn)?code>multimatch6.0.0只支持es module,而我反復(fù)嘗試都無法找到一個(gè)可以生效的jest配置(transformIgnorePatterns等配置項(xiàng)的資料都極少,這篇blog看上去操作性很強(qiáng),但嘗試后依舊無效……)。

構(gòu)建完成后,我們可以在另一個(gè)項(xiàng)目嘗試配置@hans/use-i18n-hans/no-console規(guī)則:

'@hans/use-i18n-hans/no-console': ['error', {
  excludedFiles: [
    'add-copyright-plugin.js',
    'copyright-print.js',
    'webpack-plugin-utils.js',
    'src/utils/my-eslint-plugin-tests/no-warn-folder/**/*.js',
    'tests/**/*.js',
  ],
}],

.eslintrc.js取消或添加注釋并保存,vscode應(yīng)該能立刻看到報(bào)錯(cuò)的產(chǎn)生和消失。

TODO:是否能夠mock context.getFilename(),讓本地可以寫測(cè)試用例?

發(fā)布npm包

TODO。實(shí)用的eslint規(guī)則寫好后將更新文章~

參考資料

以上就是TypeScript手寫一個(gè)簡(jiǎn)單的eslint插件實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于TypeScript eslint插件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spartacus中navigation?item?reducer實(shí)現(xiàn)解析

    Spartacus中navigation?item?reducer實(shí)現(xiàn)解析

    這篇文章主要為大家介紹了Spartacus中navigation?item?reducer實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • TypeScript類型編程中的extends和infer示例解析

    TypeScript類型編程中的extends和infer示例解析

    這篇文章主要為大家介紹了TypeScript類型編程中的extends和infer示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • TypeScript快速學(xué)習(xí)入門基礎(chǔ)語法

    TypeScript快速學(xué)習(xí)入門基礎(chǔ)語法

    TypeScript的基礎(chǔ)語法,包括變量聲明、復(fù)合類型(數(shù)組和對(duì)象)、條件控制(if-else和switch)、循環(huán)(for和while)、函數(shù)(基礎(chǔ)和箭頭函數(shù),以及可選參數(shù))、面向?qū)ο筇匦裕杜e、接口、繼承)以及模塊開發(fā)中的導(dǎo)出和導(dǎo)入
    2024-07-07
  • LocalStorage封裝一次解決方法示例

    LocalStorage封裝一次解決方法示例

    這篇文章主要為大家介紹了LocalStorage封裝一次解決的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • xterm.js在web端實(shí)現(xiàn)Terminal示例詳解

    xterm.js在web端實(shí)現(xiàn)Terminal示例詳解

    這篇文章主要為大家介紹了xterm.js在web端實(shí)現(xiàn)Terminal示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • ThreeJS使用紋理貼圖創(chuàng)建一個(gè)我的世界草地方塊

    ThreeJS使用紋理貼圖創(chuàng)建一個(gè)我的世界草地方塊

    這篇文章主要為大家介紹了ThreeJS使用紋理貼圖創(chuàng)建一個(gè)我的世界草地方塊的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • type-challenge刷題(easy部分)示例詳解

    type-challenge刷題(easy部分)示例詳解

    這篇文章主要為大家介紹了type-challenge刷題(easy部分)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • TypeScript實(shí)現(xiàn)十大排序算法之冒泡排序示例詳解

    TypeScript實(shí)現(xiàn)十大排序算法之冒泡排序示例詳解

    這篇文章主要為大家介紹了TypeScript實(shí)現(xiàn)十大排序算法之冒泡排序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 詳解什么是TypeScript里的Constructor?signature

    詳解什么是TypeScript里的Constructor?signature

    這篇文章主要介紹了什么是TypeScript里的Constructor?signature詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • TypeScript類型any never void和unknown使用場(chǎng)景區(qū)別

    TypeScript類型any never void和unknown使用場(chǎng)景區(qū)別

    這篇文章主要為大家介紹了TypeScript類型any never void和unknown使用場(chǎng)景區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10

最新評(píng)論