사용자 정의 ESLint 플러그인 작성 방법
몇 달 동안, 나는 개발자의 체험을 어떻게 맞춤형으로 만드는지 보기 위해 맞춤형 ESLint 플러그인을 만들고 싶었다.이 플러그인을 배운 경험을 여러분과 공유하고 앞으로 어떻게 자신의 플러그인을 구축할 것인가에 대한 안내를 드리고 싶습니다.
배경.
나와 나의 팀은 줄곧 고객 프로젝트를 하고 있다. 몇 달 전에 우리는 몇 가지 TypeScript 코드 스타일 약속들을 설정했다. 우리는 이러한 약속들이 우리가 인터페이스, 유형과 스타일화된 구성 요소를 관리하는 데 도움을 줄 것이라고 생각한다.
I
로 시작해야 합니다.T
로 시작해야 합니다.S
로 시작해야 합니다.나의 브리핑
나의 생각은 매우 간단하다.TypeScript 인터페이스와 유형을 분석하고 대문자
I
또는 대문자T
로 시작해야 합니다.양식화된 구성 요소를 분석하고 대문자 S
로 시작해야 한다.그것은 오류를 발견할 때 사용자에게 경고해야 할 뿐만 아니라, 이러한 번거로운 작업을 복구하기 위해 코드 해결 방안도 제공해야 한다.ESLint+AST(추상 구문 트리)
ESLint를 이해하기 위해서는 한 걸음 뒤로 물러나 ESLint의 작동 원리를 더 잘 알아야 합니다.가장 기본적인 것은 ESLint는 코드를 추상적인 문법 트리라고 부르는 것으로 해석해야 한다. 이것은 코드, 정의, 값의 표현 형식이다.컴파일러와 ESLint가 코드를 이해할 수 있는 블록으로 분해하는 방법에 대한 자세한 정보는 그 뒤에 있는 컴퓨터 과학 지식Twillio has a great guide을 참조하십시오.
플러그인 구성
간단하게 보기 위해, 본고는 TypeScript 인터페이스에 대한 ESLint 플러그인을 구축하는 방법을 소개할 것이다.
1단계: 코드 이해
우선 코드의 모든 인터페이스를 포획하고 이름 (또는 식별자) 을 찾는 방법을 찾아야 한다.이것은 인터페이스 이름이 대문자
I
로 시작하는 약속을 따르는지 확인하는 것을 허용할 것이다.추상적인 문법 트리를 시각화하기 위해AST 탐색기라는 도구를 사용할 수 있습니다.Here is an example link시작합니다.당신은 오른쪽에서 생성된AST를 보게 될 것입니다. 미친 것처럼 보이지만 실제로는 이해할 수 있습니다.오른쪽 트리 창에서 를 클릭하고
body
블록을 엽니다.기본적으로, 우리가 지금 파악하고 있는 것은 컴파일러가 당신이 작성한 코드를 어떻게 이해하는지에 관한 데이터입니다.다음과 같은 기능이 있습니다.
InterfaceDeclaration
: 인터페이스 유형Identifier
: 인터페이스의 표지(이 예는 AppProps)ObjectTypeAnnotation
: 인터페이스 내용2단계: 전환 규칙 수립
이제 우리는 해결 방안을 구축하기 시작할 수 있다.ESLint 플러그인을 고려할 때 두 부분으로 나눌 수 있습니다.'탐지기' 검사가 일치하고, '응답기' 가 오류/경고를 보내며, 코드 솔루션을 제공할 수 있습니다.AST explorer에는 '탐지기' 와 '응답기' 를 작성하고 ESLint에서 어떻게 사용하는지 볼 수 있는 편집기가 있습니다.
먼저 페이지 상단의 메뉴에서 JavaScript 옆에 있는 버튼이
babel-eslint
로 설정되어 있는지 확인합니다.그리고 '변환' 단추를 누르고 선택하십시오 ESLint v4
.transform 창에서 예시 코드를 볼 수 있습니다.ESLint 변환의 작동 방식 대부분을 설명하려면 읽어야 합니다.
TemplateLiteral
)이러한 지식을 이용하여 우리는 우리의 플러그인을 위해 해결 방안을 구축할 수 있다.
TemplateLiteral
인터페이스 형식 (InterfaceDeclaration
으로 바꾸면 오른쪽 컨트롤러에서 경고를 볼 수 있습니다.이것은 기초입니다. 지금 우리는 변압기 작업을 시범적으로 보여 줍니다.이제 우리는 진정한 해결 방안을 써야 한다.인터페이스 id의 첫 번째 문자가 자모 I인지 확인하기 위해 기본 논리를 추가합니다.
export default function (context) {
return {
InterfaceDeclaration(node) {
if (node.id.name[0] !== "I") {
context.report({
node,
message: "Interfaces must start with a capital I",
});
}
},
};
}
우리는 여전히 잘못된 소식을 볼 수 있다.I
전에 알파벳AppProps
을 붙이면 오류가 사라진다.위대했어이제 우리는 효과적인 규칙이 하나 생겼다.일이 예상대로 진행되었는지 확인하기 위해 유효하고 무효한 예를 들어 그것을 테스트한다.한 번에 하나의 예를 테스트하는 것이 더 쉬울 수 있습니다.interface Card {
preview: boolean;
}
interface Card extends Props {
preview: boolean;
}
우리는 이제 우리 팀과 개원 커뮤니티를 위해 플러그인을 구축하는 데 필요한 모든 것을 가지고 있다.3단계: 프로젝트 구축
Yeoman ESLint Builderhttps://github.com/eslint/generator-eslint#readme를 사용하여 간편한 플러그인 패키지 구축
패키지 설치:
npm i -g generator-eslint
CLI를 실행하고 지침을 따르십시오.yo eslint:plugin
TypeScript 파서를 설치해야 합니다.npm i @typescript-eslint/parser --dev
lib/rules
디렉토리에 interfaces.js
라는 새 파일을 만들고 다음 템플릿 파일을 추가합니다.module.exports = {
meta: {
type: "suggestion",
schema: [],
docs: {
description: "Enforcing the prefixing of interfaces",
},
},
create: (context) => {
return {
TSInterfaceDeclaration(node) {
if (node.id.name[0] !== "I") {
context.report({
node: node.id,
message: "Interfaces must start with a capital I",
});
}
},
};
},
};
주의해야 할 몇 가지 일:InterfaceDeclaration
'감청기'를 TSInterfaceDeclaration
로 교체한다(아래 참조)Why did I replace
InterfaceDeclaration
forTSInterfaceDeclaration
?
Thebabel-eslint
plugin doesn’t parse TypeScript but does work in the AST explorer. Using the @typescript-eslint/parser ensures we are parsing correctly, and we will add that as our parser in the next steps. This took me 2 hours to debug when writing unit tests.
마지막으로 단원 테스트를 추가합시다.
tests/lib/rules
디렉토리에 interfaces.test.js
라는 파일을 추가하고 다음 템플릿 파일을 추가합니다.const rule = require("../../../lib/rules/interfaces");
const RuleTester = require("eslint").RuleTester;
RuleTester.setDefaultConfig({
parserOptions: { ecmaVersion: 6, sourceType: "module" },
// eslint-disable-next-line node/no-unpublished-require
parser: require.resolve("@typescript-eslint/parser"),
});
const tester = new RuleTester();
tester.run("rule: interfaces", rule, {
valid: ["interface IAnotherInterface { preview: boolean; }"],
invalid: [
{
code: "interface AnotherInterface { preview: boolean; }",
errors: [{ message: "Interfaces must start with a capital I" }],
output: "interface IAnotherInterface { preview: boolean; }",
},
],
});
이 중 대부분은 ESLint 팀이 권장하는 테스트 형식입니다.여기서 주요 섹션은 TypeScript 파서를 추가하고 선언할 유효한 테스트와 잘못된 테스트를 추가하는 것입니다.ESLint 문서에서 셀 테스트에 대한 자세한 내용을 읽을 수 있습니다.5단계: 코드 수정 추가
얼마 안 남았어요.코드 복구를 추가하려면 내용에 복구 함수를 추가하십시오.보고서 객체:
fix: (fixer) => {
return [fixer.replaceText(node.id, "I" + node.id.name)];
},
마지막으로, 컴파일 단위 테스트를 확보하고 출력을 단언합니다.{
code: "interface CustomProps extends AppProps { preview: boolean; }",
errors: [{ message: "Interfaces must start with a capital I" }],
output: "interface ICustomProps extends AppProps { preview: boolean; }",
},
이렇게현재, 플러그인을 npm로 전송하거나 로컬 프로젝트에 추가할 수 있습니다.다음 단계
만약 관심이 있다면, 키워드가 자모
I
로 시작된 인터페이스를 어떻게 포착하는지 연구해야 합니다. 예를 들어 InfoBoxProps
.이 플러그인은 infobox
이나 idProps
같은 이상한 인터페이스 이름이 있는 가장자리 상황을 더 잘 지원해야 한다. 왜냐하면 우리의 일치로 현재 이 이름을 포착할 수 없기 때문이다.Wait, why isn’t the plugin written in TypeScript too
Good question. It can be, but to keep things simple I opted to just build it in vanilla JS. If I’m adding a lot more rules or working on this project with others, then switching to a TypeScript toolchain would be a great idea
이것은 아마도 내가 네 번째로 ESLint 플러그인을 구축하려고 시도한 것일 것이다.연구를 진행할 때, 나는 API 문서와 다른 사람들이 작성한 대부분의 안내서와 강좌가 가장 간단한 플러그인 아이디어라도 읽고 이해하기 어렵다는 것을 발견했다.이 안내서가 당신의 시작을 도울 수 있기를 바랍니다.
너는 나의 리포와 나의 인터페이스 예시, 그리고 내가 여기서 만든 다른 두 가지 (하나는 유형에 사용되고, 하나는 스타일화된 구성 요소에 사용된다) 를 볼 수 있다.
콰이밍 / eslint 플러그인 접두사 유형
인터페이스, 유형 및 스타일 지정 구성 요소의 접두어를 강제로 적용하는 ESLint 플러그인
!
Reference
이 문제에 관하여(사용자 정의 ESLint 플러그인 작성 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kwaimind/how-to-write-custom-eslint-plugins-173k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)