Skip to content

Commit ca8d981

Browse files
authored
[new-rule] add jsx-space-before-trailing-slash rule (#164)
1 parent 8cc1219 commit ca8d981

File tree

4 files changed

+81
-0
lines changed

4 files changed

+81
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ The built-in configuration preset you get with `"extends": "tslint-react"` is se
100100
<div className="foo" />
101101
```
102102
- Rule options: _none_
103+
- `jsx-space-before-trailing-slash`
104+
- Checks that self-closing JSX elements have a space before the '/>' part.
105+
- Rule options: _none_
103106
- `jsx-wrap-multiline` (since v2.1)
104107
- Enforces that multiline JSX expressions are wrapped with parentheses.
105108
- Opening parenthesis must be followed by a newline.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* @license
3+
* Copyright 2016 Palantir Technologies, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import * as Lint from "tslint";
19+
import { isJsxSelfClosingElement } from "tsutils";
20+
import * as ts from "typescript";
21+
22+
export class Rule extends Lint.Rules.AbstractRule {
23+
/* tslint:disable:object-literal-sort-keys */
24+
public static metadata: Lint.IRuleMetadata = {
25+
ruleName: "jsx-space-before-trailing-slash",
26+
description: "Checks that self-closing JSX elements have a space before the '/>' part.",
27+
options: null,
28+
optionsDescription: "",
29+
optionExamples: ["true"],
30+
type: "style",
31+
typescriptOnly: false,
32+
};
33+
/* tslint:enable:object-literal-sort-keys */
34+
35+
public static FAILURE_STRING = "Self-closing JSX elements must have a space before the '/>' part";
36+
37+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
38+
return this.applyWithFunction(sourceFile, walk);
39+
}
40+
}
41+
42+
const closingLength = "/>".length;
43+
const isWhiteSpace = (char: string) => /\s/.test(char);
44+
const hasWhitespaceBeforeClosing = (nodeText: string) =>
45+
isWhiteSpace(nodeText.charAt(nodeText.length - closingLength - 1));
46+
47+
function walk(ctx: Lint.WalkContext<void>): void {
48+
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
49+
if (isJsxSelfClosingElement(node)) {
50+
if (!hasWhitespaceBeforeClosing(node.getText(ctx.sourceFile))) {
51+
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
52+
}
53+
}
54+
return ts.forEachChild(node, cb);
55+
});
56+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div>
2+
Contents
3+
</div>
4+
5+
<span/>
6+
~~~~~~~ [Self-closing JSX elements must have a space before the '/>' part]
7+
8+
<button />
9+
10+
<h2 class="colouring" contents="B"/>
11+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Self-closing JSX elements must have a space before the '/>' part]
12+
13+
<button onClick="run()" />
14+
15+
<img
16+
src="./foo/bar.png"
17+
/>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rules": {
3+
"jsx-space-before-trailing-slash": true
4+
}
5+
}

0 commit comments

Comments
 (0)