Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Commit

Permalink
Enforce quote mark in JSX attributes.
Browse files Browse the repository at this point in the history
  • Loading branch information
meowtec committed Jan 13, 2016
1 parent fac7c9a commit 830e957
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
19 changes: 14 additions & 5 deletions src/rules/quotemarkRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,47 @@ export class Rule extends Lint.Rules.AbstractRule {

class QuotemarkWalker extends Lint.RuleWalker {
private quoteMark = QuoteMark.DOUBLE_QUOTES;
private jsxQuoteMark: QuoteMark;
private avoidEscape: boolean;

constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) {
super(sourceFile, options);

const ruleArguments = this.getOptions();
const quoteMarkString = ruleArguments[0];
if (quoteMarkString === "single") {

if (ruleArguments.indexOf("single") > -1) {
this.quoteMark = QuoteMark.SINGLE_QUOTES;
}

if (ruleArguments.indexOf("jsx-single") > -1) {
this.jsxQuoteMark = QuoteMark.SINGLE_QUOTES;
} else if (ruleArguments.indexOf("jsx-double") > -1) {
this.jsxQuoteMark = QuoteMark.DOUBLE_QUOTES;
} else {
this.quoteMark = QuoteMark.DOUBLE_QUOTES;
this.jsxQuoteMark = this.quoteMark;
}

this.avoidEscape = ruleArguments.indexOf("avoid-escape") > 0;
}

public visitStringLiteral(node: ts.StringLiteral) {
const inJsx = (node.parent.kind === ts.SyntaxKind.JsxAttribute);
const text = node.getText();
const width = node.getWidth();
const position = node.getStart();

const firstCharacter = text.charAt(0);
const lastCharacter = text.charAt(text.length - 1);

const expectedQuoteMark = (this.quoteMark === QuoteMark.SINGLE_QUOTES) ? "'" : "\"";
const quoteMark = inJsx ? this.jsxQuoteMark : this.quoteMark;
const expectedQuoteMark = (quoteMark === QuoteMark.SINGLE_QUOTES) ? "'" : "\"";

if (firstCharacter !== expectedQuoteMark || lastCharacter !== expectedQuoteMark) {
// allow the "other" quote mark to be used, but only to avoid having to escape
const includesOtherQuoteMark = text.slice(1, -1).indexOf(expectedQuoteMark) !== -1;

if (!(this.avoidEscape && includesOtherQuoteMark)) {
const failureMessage = (this.quoteMark === QuoteMark.SINGLE_QUOTES)
const failureMessage = (quoteMark === QuoteMark.SINGLE_QUOTES)
? Rule.SINGLE_QUOTE_FAILURE
: Rule.DOUBLE_QUOTE_FAILURE;

Expand Down
5 changes: 5 additions & 0 deletions test/files/rules/quotemark.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as React from "react";

export const a = (
<div className="class" id='id' data-a={'a' + "b"}></div>
)
28 changes: 28 additions & 0 deletions test/rules/quotemarkRuleTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {TestUtils} from "../lint";
describe("<quotemark>", () => {
const QuoteMarkRule = TestUtils.getRule("quotemark");
const fileName = "rules/quotemark.test.ts";
const tsxFileName = "rules/quotemark.test.tsx";
const singleFailureString = QuoteMarkRule.SINGLE_QUOTE_FAILURE;
const doubleFailureString = QuoteMarkRule.DOUBLE_QUOTE_FAILURE;

Expand Down Expand Up @@ -61,4 +62,31 @@ describe("<quotemark>", () => {
assert.equal(actualFailures.length, 1);
assert.isTrue(actualFailures[0].equals(expectedFailure));
});

it("enforces double quotes and jsx single quotes", () => {
const actualFailures = TestUtils.applyRuleOnFile(tsxFileName, QuoteMarkRule, [true, "double", "jsx-single"]);

const expectedFailures = [
TestUtils.createFailure(tsxFileName, [4, 20], [4, 27], singleFailureString),
TestUtils.createFailure(tsxFileName, [4, 44], [4, 47], doubleFailureString)
];
assert.equal(actualFailures.length, 2);
assert.isTrue(actualFailures[0].equals(expectedFailures[0]));
assert.isTrue(actualFailures[1].equals(expectedFailures[1]));
});

it("enforces single quotes and jsx double quotes", () => {
const actualFailures = TestUtils.applyRuleOnFile(tsxFileName, QuoteMarkRule, [true, "single", "jsx-double"]);

const expectedFailures = [
TestUtils.createFailure(tsxFileName, [1, 24], [1, 31], singleFailureString),
TestUtils.createFailure(tsxFileName, [4, 31], [4, 35], doubleFailureString),
TestUtils.createFailure(tsxFileName, [4, 50], [4, 53], singleFailureString)
];
assert.equal(actualFailures.length, 3);
assert.isTrue(actualFailures[0].equals(expectedFailures[0]));
assert.isTrue(actualFailures[1].equals(expectedFailures[1]));
assert.isTrue(actualFailures[2].equals(expectedFailures[2]));
});

});

1 comment on commit 830e957

@syamn
Copy link

@syamn syamn commented on 830e957 Apr 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Please sign in to comment.