diff --git a/src/rules/quotemarkRule.ts b/src/rules/quotemarkRule.ts index fbc79d3545c..190803873f8 100644 --- a/src/rules/quotemarkRule.ts +++ b/src/rules/quotemarkRule.ts @@ -43,23 +43,31 @@ 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(); @@ -67,14 +75,15 @@ class QuotemarkWalker extends Lint.RuleWalker { 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; diff --git a/test/files/rules/quotemark.test.tsx b/test/files/rules/quotemark.test.tsx new file mode 100644 index 00000000000..29a1d305949 --- /dev/null +++ b/test/files/rules/quotemark.test.tsx @@ -0,0 +1,5 @@ +import * as React from "react"; + +export const a = ( +
+) diff --git a/test/rules/quotemarkRuleTests.ts b/test/rules/quotemarkRuleTests.ts index 0bab400a0f1..344bffd3a03 100644 --- a/test/rules/quotemarkRuleTests.ts +++ b/test/rules/quotemarkRuleTests.ts @@ -19,6 +19,7 @@ import {TestUtils} from "../lint"; describe("", () => { 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; @@ -61,4 +62,31 @@ describe("", () => { 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])); + }); + });