From b933c36ac2c8dad2d681cf6ea880089ff8a16c16 Mon Sep 17 00:00:00 2001 From: paibamboo Date: Thu, 14 Mar 2019 15:47:11 +0700 Subject: [PATCH] feat: jsxSpaceBeforeTrailingSlashRule --- src/jsxSpaceBeforeTrailingSlashRule.ts | 41 +++++++++++++++++++ .../default/test.tsx.lint | 23 +++++++++++ .../default/tsconfig.json | 7 ++++ .../default/tslint.json | 8 ++++ .../never/test.tsx.lint | 23 +++++++++++ .../never/tsconfig.json | 7 ++++ .../never/tslint.json | 8 ++++ 7 files changed, 117 insertions(+) create mode 100644 src/jsxSpaceBeforeTrailingSlashRule.ts create mode 100644 test/rules/jsx-space-before-trailing-slash/default/test.tsx.lint create mode 100644 test/rules/jsx-space-before-trailing-slash/default/tsconfig.json create mode 100644 test/rules/jsx-space-before-trailing-slash/default/tslint.json create mode 100644 test/rules/jsx-space-before-trailing-slash/never/test.tsx.lint create mode 100644 test/rules/jsx-space-before-trailing-slash/never/tsconfig.json create mode 100644 test/rules/jsx-space-before-trailing-slash/never/tslint.json diff --git a/src/jsxSpaceBeforeTrailingSlashRule.ts b/src/jsxSpaceBeforeTrailingSlashRule.ts new file mode 100644 index 0000000..0e557f5 --- /dev/null +++ b/src/jsxSpaceBeforeTrailingSlashRule.ts @@ -0,0 +1,41 @@ +import * as Lint from "tslint"; +import * as ts from "typescript"; + +class JsxSpaceBeforeTrailingSlashRule extends Lint.RuleWalker { + private readonly enforceWhiteSpace: boolean = true; + constructor( + sourceFile: ts.SourceFile, + options: Lint.IOptions + ) { + super(sourceFile, options); + if (options.ruleArguments[0] === "never") { + this.enforceWhiteSpace = false; + } + } + + private static hasWhitespaceBeforeClosing(nodeText: string): boolean { + return /\s/.test(nodeText.charAt(nodeText.length - "/>".length - 1)); + } + + public visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): void { + super.visitJsxSelfClosingElement(node); + if (this.enforceWhiteSpace) { + if (!JsxSpaceBeforeTrailingSlashRule.hasWhitespaceBeforeClosing(node.getText())) { + this.addFailureAtNode(node, "Self-closing JSX elements must have a space before the '/>' part"); + return; + } + } else { + if (!/[\r\n]/.test(node.getText()) && JsxSpaceBeforeTrailingSlashRule.hasWhitespaceBeforeClosing(node.getText())) { + this.addFailureAtNode(node, "One-line self-closing JSX elements must not have a space(s) before the '/>' part"); + return; + } + } + } +} + +// tslint:disable-next-line:export-name max-classes-per-file +export class Rule extends Lint.Rules.TypedRule { + public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] { + return this.applyWithWalker(new JsxSpaceBeforeTrailingSlashRule(sourceFile, this.getOptions())); + } +} diff --git a/test/rules/jsx-space-before-trailing-slash/default/test.tsx.lint b/test/rules/jsx-space-before-trailing-slash/default/test.tsx.lint new file mode 100644 index 0000000..8236569 --- /dev/null +++ b/test/rules/jsx-space-before-trailing-slash/default/test.tsx.lint @@ -0,0 +1,23 @@ +
+ Contents +
+ + +~~~~~~~ [Self-closing JSX elements must have a space before the '/>' part] + +