From e17512adcd21c23b3bbf3c8308c2f988ec89fb56 Mon Sep 17 00:00:00 2001 From: Stefan Mirea Date: Sun, 4 Nov 2018 16:36:00 -0500 Subject: [PATCH] Add an option to print single quotes in JSX (#4798) * feat(option-singleQuote-jsx): Added jsSingleQuote * feat(option-singleQuote-jsx): Refactored to use a simple jsxSingleQuote flag * feat(option-singleQuote-jsx): Fixed borked rebase * feat(option-singleQuote-jsx): Updated snapshots * feat(option-singleQuote-jsx): Resolved pending comments * feat(option-singleQuote-jsx): Removed assert * Fixed merge conflicts * Updated snapshots after merge conflicts --- docs/options.md | 10 +- src/common/util.js | 38 +- src/language-js/options.js | 7 + src/language-js/printer-estree.js | 19 +- tests/jsx/__snapshots__/jsfmt.spec.js.snap | 3486 ++++++++++++++++- tests/jsx/jsfmt.spec.js | 17 +- tests/jsx/quotes.js | 33 + .../__snapshots__/early-exit.js.snap | 4 + .../__snapshots__/help-options.js.snap | 13 + .../__tests__/__snapshots__/schema.js.snap | 5 + .../__snapshots__/support-info.js.snap | 25 +- 11 files changed, 3632 insertions(+), 25 deletions(-) diff --git a/docs/options.md b/docs/options.md index 2fedcbd5..46b6b9b5 100644 --- a/docs/options.md +++ b/docs/options.md @@ -60,7 +60,7 @@ Use single quotes instead of double quotes. Notes: -- Quotes in JSX will always be double and ignore this setting. +- JSX quotes ignore this option – see [jsx-single-quote](#jsx-single-quote). - If the number of quotes outweighs the other quote, the quote which is less used will be used to format the string - Example: `"I'm double quoted"` results in `"I'm double quoted"` and `"This \"example\" is single quoted"` results in `'This "example" is single quoted'`. See the [strings rationale](rationale.md#strings) for more information. @@ -69,6 +69,14 @@ See the [strings rationale](rationale.md#strings) for more information. | ------- | ---------------- | --------------------- | | `false` | `--single-quote` | `singleQuote: ` | +## JSX Quotes + +Use single quotes instead of double quotes in JSX. + +| Default | CLI Override | API Override | +| ------- | -------------------- | ------------------------ | +| `false` | `--jsx-single-quote` | `jsxSingleQuote: ` | + ## Trailing Commas Print trailing commas wherever possible when multi-line. (A single-line array, for example, never gets trailing commas.) diff --git a/src/common/util.js b/src/common/util.js index 7bea29ca..bea82d17 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -430,7 +430,7 @@ function getIndentSize(value, tabWidth) { ); } -function printString(raw, options, isDirectiveLiteral) { +function getPreferredQuote(raw, preferredQuote) { // `rawContent` is the string exactly like it appeared in the input source // code, without its enclosing quotes. const rawContent = raw.slice(1, -1); @@ -438,17 +438,14 @@ function printString(raw, options, isDirectiveLiteral) { const double = { quote: '"', regex: /"/g }; const single = { quote: "'", regex: /'/g }; - const preferred = options.singleQuote ? single : double; + const preferred = preferredQuote === "'" ? single : double; const alternate = preferred === single ? double : single; - let shouldUseAlternateQuote = false; - let canChangeDirectiveQuotes = false; + let result = preferred.quote; // If `rawContent` contains at least one of the quote preferred for enclosing // the string, we might want to enclose with the alternate quote instead, to // minimize the number of escaped quotes. - // Also check for the alternate quote, to determine if we're allowed to swap - // the quotes on a DirectiveLiteral. if ( rawContent.includes(preferred.quote) || rawContent.includes(alternate.quote) @@ -456,19 +453,31 @@ function printString(raw, options, isDirectiveLiteral) { const numPreferredQuotes = (rawContent.match(preferred.regex) || []).length; const numAlternateQuotes = (rawContent.match(alternate.regex) || []).length; - shouldUseAlternateQuote = numPreferredQuotes > numAlternateQuotes; - } else { - canChangeDirectiveQuotes = true; + result = + numPreferredQuotes > numAlternateQuotes + ? alternate.quote + : preferred.quote; } + return result; +} + +function printString(raw, options, isDirectiveLiteral) { + // `rawContent` is the string exactly like it appeared in the input source + // code, without its enclosing quotes. + const rawContent = raw.slice(1, -1); + + // Check for the alternate quote, to determine if we're allowed to swap + // the quotes on a DirectiveLiteral. + const canChangeDirectiveQuotes = + !rawContent.includes('"') && !rawContent.includes("'"); + const enclosingQuote = options.parser === "json" - ? double.quote + ? '"' : options.__isInHtmlAttribute - ? single.quote - : shouldUseAlternateQuote - ? alternate.quote - : preferred.quote; + ? "'" + : getPreferredQuote(raw, options.singleQuote ? "'" : '"'); // Directives are exact code unit sequences, which means that you can't // change the escape sequences they use. @@ -691,6 +700,7 @@ module.exports = { startsWithNoLookaheadToken, getAlignmentSize, getIndentSize, + getPreferredQuote, printString, printNumber, hasIgnoreComment, diff --git a/src/language-js/options.js b/src/language-js/options.js index 2635f7f1..a20e269f 100644 --- a/src/language-js/options.js +++ b/src/language-js/options.js @@ -41,6 +41,13 @@ module.exports = { "Do not print semicolons, except at the beginning of lines which may need them." }, singleQuote: commonOptions.singleQuote, + jsxSingleQuote: { + since: "1.15.0", + category: CATEGORY_JAVASCRIPT, + type: "boolean", + default: false, + description: "Use single quotes in JSX." + }, trailingComma: { since: "0.0.0", category: CATEGORY_JAVASCRIPT, diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 515eda80..27167a80 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -20,7 +20,8 @@ const { getPenultimate, startsWithNoLookaheadToken, getIndentSize, - matchAncestorTypes + matchAncestorTypes, + getPreferredQuote } = require("../common/util"); const { isNextLineEmpty, @@ -33,8 +34,8 @@ const clean = require("./clean"); const insertPragma = require("./pragma").insertPragma; const handleComments = require("./comments"); const pathNeedsParens = require("./needs-parens"); -const preprocess = require("./preprocess"); const { printHtmlBinding } = require("./html-binding"); +const preprocess = require("./preprocess"); const { hasNode, hasFlowAnnotationComment, @@ -1948,8 +1949,16 @@ function printPathNoParens(path, options, print, args) { if (n.value) { let res; if (isStringLiteral(n.value)) { - const value = rawText(n.value); - res = '"' + value.slice(1, -1).replace(/"/g, """) + '"'; + const raw = rawText(n.value); + // Unescape all quotes so we get an accurate preferred quote + let final = raw.replace(/'/g, "'").replace(/"/g, '"'); + const quote = getPreferredQuote( + final, + options.jsxSingleQuote ? "'" : '"' + ); + const escape = quote === "'" ? "'" : """; + final = final.slice(1, -1).replace(new RegExp(quote, "g"), escape); + res = concat([quote, final, quote]); } else { res = path.call(print, "value"); } @@ -5257,7 +5266,7 @@ function printJSXElement(path, options, print) { containsMultipleAttributes || containsMultipleExpressions; - const rawJsxWhitespace = options.singleQuote ? "{' '}" : '{" "}'; + const rawJsxWhitespace = options.jsxSingleQuote ? "{' '}" : '{" "}'; const jsxWhitespace = ifBreak(concat([rawJsxWhitespace, softline]), " "); const isFacebookTranslationTag = diff --git a/tests/jsx/__snapshots__/jsfmt.spec.js.snap b/tests/jsx/__snapshots__/jsfmt.spec.js.snap index f13e5288..6554eb70 100644 --- a/tests/jsx/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx/__snapshots__/jsfmt.spec.js.snap @@ -69,6 +69,213 @@ const TodoList = ({ todos }) => ( `; +exports[`array-iter.js - flow-verify 2`] = ` +const UsersList = ({ users }) => ( +
+

Users list

+
    + {users.map(user => ( +
  • {user.name}
  • + ))} +
+
+) + +const TodoList = ({ todos }) => ( +
+
    {_.map(todos, (todo, i) => )}
+
+); + +
+ {scopes + .filter(scope => scope.value !== '') + .map((scope, i) => ( + + ))} +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const UsersList = ({ users }) => ( +
+

Users list

+
    + {users.map(user => ( +
  • {user.name}
  • + ))} +
+
+); + +const TodoList = ({ todos }) => ( +
+
    + {_.map(todos, (todo, i) => ( + + ))} +
+
+); + +
+ {scopes + .filter(scope => scope.value !== "") + .map((scope, i) => ( + + ))} +
; + +`; + +exports[`array-iter.js - flow-verify 3`] = ` +const UsersList = ({ users }) => ( +
+

Users list

+
    + {users.map(user => ( +
  • {user.name}
  • + ))} +
+
+) + +const TodoList = ({ todos }) => ( +
+
    {_.map(todos, (todo, i) => )}
+
+); + +
+ {scopes + .filter(scope => scope.value !== '') + .map((scope, i) => ( + + ))} +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const UsersList = ({ users }) => ( +
+

Users list

+
    + {users.map(user => ( +
  • {user.name}
  • + ))} +
+
+); + +const TodoList = ({ todos }) => ( +
+
    + {_.map(todos, (todo, i) => ( + + ))} +
+
+); + +
+ {scopes + .filter(scope => scope.value !== '') + .map((scope, i) => ( + + ))} +
; + +`; + +exports[`array-iter.js - flow-verify 4`] = ` +const UsersList = ({ users }) => ( +
+

Users list

+
    + {users.map(user => ( +
  • {user.name}
  • + ))} +
+
+) + +const TodoList = ({ todos }) => ( +
+
    {_.map(todos, (todo, i) => )}
+
+); + +
+ {scopes + .filter(scope => scope.value !== '') + .map((scope, i) => ( + + ))} +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const UsersList = ({ users }) => ( +
+

Users list

+
    + {users.map(user => ( +
  • {user.name}
  • + ))} +
+
+); + +const TodoList = ({ todos }) => ( +
+
    + {_.map(todos, (todo, i) => ( + + ))} +
+
+); + +
+ {scopes + .filter(scope => scope.value !== '') + .map((scope, i) => ( + + ))} +
; + +`; + exports[`attr-comments.js - flow-verify 1`] = ` fn(arg) + } + propArrowWithBreak={ + // comment + arg => + fn({ + makeItBreak + }) + } + propArray={ + // comment + [el1, el2] + } + propObj={ + // comment + { key: val } + } + propTemplate={ + // comment + \`text\` + } +/>; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + fn(arg) + } + propArrowWithBreak={ + // comment + arg => + fn({ + makeItBreak + }) + } + propArray={ + // comment + [el1, el2] + } + propObj={ + // comment + { key: val } + } + propTemplate={ + // comment + \`text\` + } +/>; + +`; + +exports[`attr-comments.js - flow-verify 3`] = ` + fn(arg) + } + propArrowWithBreak={ + // comment + arg => + fn({ + makeItBreak + }) + } + propArray={ + // comment + [el1, el2] + } + propObj={ + // comment + { key: val } + } + propTemplate={ + // comment + \`text\` + } +/>; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + fn(arg) + } + propArrowWithBreak={ + // comment + arg => + fn({ + makeItBreak + }) + } + propArray={ + // comment + [el1, el2] + } + propObj={ + // comment + { key: val } + } + propTemplate={ + // comment + \`text\` + } +/>; + +`; + +exports[`attr-comments.js - flow-verify 4`] = ` + fn(arg) + } + propArrowWithBreak={ + // comment + arg => + fn({ + makeItBreak + }) + } + propArray={ + // comment + [el1, el2] + } + propObj={ + // comment + { key: val } + } + propTemplate={ + // comment + \`text\` + } +/>; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + fn(arg) + } + propArrowWithBreak={ + // comment + arg => + fn({ + makeItBreak + }) + } + propArray={ + // comment + [el1, el2] + } + propObj={ + // comment + { key: val } + } + propTemplate={ + // comment + \`text\` + } +/>; + +`; + exports[`conditional-expression.js - flow-verify 1`] = ` // There are two ways to print ConditionalExpressions: "normal mode" and // "JSX mode". This is normal mode (when breaking): @@ -415,6 +823,843 @@ cable ? ( `; +exports[`conditional-expression.js - flow-verify 2`] = ` +// There are two ways to print ConditionalExpressions: "normal mode" and +// "JSX mode". This is normal mode (when breaking): +// +// test +// ? consequent +// : alternate; +// +// And this is JSX mode (when breaking): +// +// test ? ( +// consequent +// ) : ( +// alternate +// ); +// +// When non-breaking, they look the same: +// +// test ? consequent : alternate; +// +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. +// Otherwise, we print in normal mode. + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. +normalModeNonBreaking ? "a" : "b"; + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. +normalModeBreaking + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is non-breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
? jsxModeFromElementNonBreaking : "a"; + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ?
: "a"; + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ? "a" :
; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
? ( + "jsx mode from element breaking" +) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( + "a" +) : ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+); + +// This chain of ConditionalExpressions prints in JSX mode because the parent of +// the outermost ConditionalExpression is a JSXExpressionContainer. It is +// non-breaking. +
+ {a ? "a" : b ? "b" : "c"} +
; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is non-breaking. +cable ? "satellite" : public ? "affairs" : network ? : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the end). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( + "satellite" +) : public ? ( + "affairs" +) : network ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the beginning). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : sateline ? ( + "public" +) : affairs ? ( + "network" +) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// There are two ways to print ConditionalExpressions: "normal mode" and +// "JSX mode". This is normal mode (when breaking): +// +// test +// ? consequent +// : alternate; +// +// And this is JSX mode (when breaking): +// +// test ? ( +// consequent +// ) : ( +// alternate +// ); +// +// When non-breaking, they look the same: +// +// test ? consequent : alternate; +// +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. +// Otherwise, we print in normal mode. + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. +normalModeNonBreaking ? "a" : "b"; + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. +normalModeBreaking + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is non-breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
? jsxModeFromElementNonBreaking : "a"; + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ?
: "a"; + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ? "a" :
; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
? ( + "jsx mode from element breaking" +) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( + "a" +) : ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+); + +// This chain of ConditionalExpressions prints in JSX mode because the parent of +// the outermost ConditionalExpression is a JSXExpressionContainer. It is +// non-breaking. +
{a ? "a" : b ? "b" : "c"}
; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is non-breaking. +cable ? "satellite" : public ? "affairs" : network ? : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the end). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( + "satellite" +) : public ? ( + "affairs" +) : network ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : ( + "dunno" +); + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the beginning). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : sateline ? ( + "public" +) : affairs ? ( + "network" +) : ( + "dunno" +); + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; + +`; + +exports[`conditional-expression.js - flow-verify 3`] = ` +// There are two ways to print ConditionalExpressions: "normal mode" and +// "JSX mode". This is normal mode (when breaking): +// +// test +// ? consequent +// : alternate; +// +// And this is JSX mode (when breaking): +// +// test ? ( +// consequent +// ) : ( +// alternate +// ); +// +// When non-breaking, they look the same: +// +// test ? consequent : alternate; +// +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. +// Otherwise, we print in normal mode. + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. +normalModeNonBreaking ? "a" : "b"; + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. +normalModeBreaking + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is non-breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
? jsxModeFromElementNonBreaking : "a"; + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ?
: "a"; + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ? "a" :
; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
? ( + "jsx mode from element breaking" +) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( + "a" +) : ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+); + +// This chain of ConditionalExpressions prints in JSX mode because the parent of +// the outermost ConditionalExpression is a JSXExpressionContainer. It is +// non-breaking. +
+ {a ? "a" : b ? "b" : "c"} +
; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is non-breaking. +cable ? "satellite" : public ? "affairs" : network ? : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the end). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( + "satellite" +) : public ? ( + "affairs" +) : network ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the beginning). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : sateline ? ( + "public" +) : affairs ? ( + "network" +) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// There are two ways to print ConditionalExpressions: "normal mode" and +// "JSX mode". This is normal mode (when breaking): +// +// test +// ? consequent +// : alternate; +// +// And this is JSX mode (when breaking): +// +// test ? ( +// consequent +// ) : ( +// alternate +// ); +// +// When non-breaking, they look the same: +// +// test ? consequent : alternate; +// +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. +// Otherwise, we print in normal mode. + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. +normalModeNonBreaking ? 'a' : 'b'; + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. +normalModeBreaking + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : 'c'; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is non-breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
? jsxModeFromElementNonBreaking : 'a'; + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ?
: 'a'; + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ? 'a' :
; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
? ( + 'jsx mode from element breaking' +) : ( + 'a' +); + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : ( + 'a' +); + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( + 'a' +) : ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+); + +// This chain of ConditionalExpressions prints in JSX mode because the parent of +// the outermost ConditionalExpression is a JSXExpressionContainer. It is +// non-breaking. +
{a ? 'a' : b ? 'b' : 'c'}
; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is non-breaking. +cable ? 'satellite' : public ? 'affairs' : network ? : 'dunno'; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the end). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( + 'satellite' +) : public ? ( + 'affairs' +) : network ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : ( + 'dunno' +); + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the beginning). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : sateline ? ( + 'public' +) : affairs ? ( + 'network' +) : ( + 'dunno' +); + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; + +`; + +exports[`conditional-expression.js - flow-verify 4`] = ` +// There are two ways to print ConditionalExpressions: "normal mode" and +// "JSX mode". This is normal mode (when breaking): +// +// test +// ? consequent +// : alternate; +// +// And this is JSX mode (when breaking): +// +// test ? ( +// consequent +// ) : ( +// alternate +// ); +// +// When non-breaking, they look the same: +// +// test ? consequent : alternate; +// +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. +// Otherwise, we print in normal mode. + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. +normalModeNonBreaking ? "a" : "b"; + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. +normalModeBreaking + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : "c"; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is non-breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
? jsxModeFromElementNonBreaking : "a"; + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ?
: "a"; + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ? "a" :
; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
? ( + "jsx mode from element breaking" +) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : ( + "a" +); + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( + "a" +) : ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+); + +// This chain of ConditionalExpressions prints in JSX mode because the parent of +// the outermost ConditionalExpression is a JSXExpressionContainer. It is +// non-breaking. +
+ {a ? "a" : b ? "b" : "c"} +
; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is non-breaking. +cable ? "satellite" : public ? "affairs" : network ? : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the end). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( + "satellite" +) : public ? ( + "affairs" +) : network ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the beginning). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( +
+ thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo +
+) : sateline ? ( + "public" +) : affairs ? ( + "network" +) : "dunno"; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// There are two ways to print ConditionalExpressions: "normal mode" and +// "JSX mode". This is normal mode (when breaking): +// +// test +// ? consequent +// : alternate; +// +// And this is JSX mode (when breaking): +// +// test ? ( +// consequent +// ) : ( +// alternate +// ); +// +// When non-breaking, they look the same: +// +// test ? consequent : alternate; +// +// We only print a conditional expression in JSX mode if its test, +// consequent, or alternate are JSXElements. +// Otherwise, we print in normal mode. + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// The line does not break. +normalModeNonBreaking ? 'a' : 'b'; + +// This ConditionalExpression has no JSXElements so it prints in normal mode. +// Its consequent is very long, so it breaks out to multiple lines. +normalModeBreaking + ? johnJacobJingleHeimerSchmidtHisNameIsMyNameTooWheneverWeGoOutThePeopleAlwaysShoutThereGoesJohnJacobJingleHeimerSchmidtYaDaDaDaDaDaDa + : 'c'; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is non-breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
? jsxModeFromElementNonBreaking : 'a'; + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ?
: 'a'; + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is non-breaking. +jsxModeFromElementNonBreaking ? 'a' :
; + +// This ConditionalExpression prints in JSX mode because its test is a +// JSXElement. It is breaking. +// Note: I have never, ever seen someone use a JSXElement as the test in a +// ConditionalExpression. But this test is included for completeness. +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
? ( + 'jsx mode from element breaking' +) : ( + 'a' +); + +// This ConditionalExpression prints in JSX mode because its consequent is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : ( + 'a' +); + +// This ConditionalExpression prints in JSX mode because its alternate is a +// JSXElement. It is breaking. +jsxModeFromElementBreaking ? ( + 'a' +) : ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+); + +// This chain of ConditionalExpressions prints in JSX mode because the parent of +// the outermost ConditionalExpression is a JSXExpressionContainer. It is +// non-breaking. +
{a ? 'a' : b ? 'b' : 'c'}
; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is non-breaking. +cable ? 'satellite' : public ? 'affairs' : network ? : 'dunno'; + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the end). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( + 'satellite' +) : public ? ( + 'affairs' +) : network ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : ( + 'dunno' +); + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain (in this case, at the beginning). It is +// breaking; notice the consequents and alternates in the entire chain get +// wrapped in parens. +cable ? ( +
+ + thisIsASongAboutYourPoorSickPenguinHeHasAFeverAndHisToesAreBlueButIfISingToYourPoorSickPenguinHeWillFeelBetterInADayOrTwo + +
+) : sateline ? ( + 'public' +) : affairs ? ( + 'network' +) : ( + 'dunno' +); + +// This chain of ConditionalExpressions prints in JSX mode because there is a +// JSX element somewhere in the chain. It is breaking; notice the consequents +// and alternates in the entire chain get wrapped in parens. +
+ {properties.length > 1 || + (properties.length === 1 && properties[0].apps.size > 1) ? ( + draggingApp == null || newPropertyName == null ? ( + + ) : ( + + ) + ) : null} +
; + +`; + exports[`expression.js - flow-verify 1`] = ` ; + +; + + + {() => ( + + + + )} +; + + + {items.map(item => ( + + + + ))} +; + + + {function() { + return ( + + + + ); + }} +; + +; + + + test + +}/>; + + doLogClick("short", "short", data)} +/>; + + + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + } +/>; + + { + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + }} +/>; + +, + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +/>; + + + {data => doLogClick("short", "short", data)} +; + + + {data => + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + } +; + + + {data => { + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + }} +; + + + {( + key: "possible_key_1" | "possible_key_2" | "possible_key_3", + value: string | Immutable.List, + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; + +; + + + {() => ( + + + + )} +; + + + {items.map(item => ( + + + + ))} +; + + + {function() { + return ( + + + + ); + }} +; + +; + +test} />; + + doLogClick("short", "short", data)} +/>; + + + doLogClick( + "long_name_long_name_long_name", + "long_name_long_name_long_name", + data + ) + } +/>; + + { + doLogClick( + "long_name_long_name_long_name", + "long_name_long_name_long_name", + data + ); + }} +/>; + + + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +/>; + + + {data => doLogClick("short", "short", data)} +; + + + {data => + doLogClick( + "long_name_long_name_long_name", + "long_name_long_name_long_name", + data + ) + } +; + + + {data => { + doLogClick( + "long_name_long_name_long_name", + "long_name_long_name_long_name", + data + ); + }} +; + + + {( + key: "possible_key_1" | "possible_key_2" | "possible_key_3", + value: string | Immutable.List + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +; + +`; + +exports[`expression.js - flow-verify 3`] = ` +; + +; + + + {() => ( + + + + )} +; + + + {items.map(item => ( + + + + ))} +; + + + {function() { + return ( + + + + ); + }} +; + +; + + + test + +}/>; + + doLogClick("short", "short", data)} +/>; + + + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + } +/>; + + { + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + }} +/>; + +, + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +/>; + + + {data => doLogClick("short", "short", data)} +; + + + {data => + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + } +; + + + {data => { + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + }} +; + + + {( + key: "possible_key_1" | "possible_key_2" | "possible_key_3", + value: string | Immutable.List, + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; + +; + + + {() => ( + + + + )} +; + + + {items.map(item => ( + + + + ))} +; + + + {function() { + return ( + + + + ); + }} +; + +; + +test} />; + + doLogClick('short', 'short', data)} +/>; + + + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ) + } +/>; + + { + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ); + }} +/>; + + + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +/>; + + + {data => doLogClick('short', 'short', data)} +; + + + {data => + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ) + } +; + + + {data => { + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ); + }} +; + + + {( + key: 'possible_key_1' | 'possible_key_2' | 'possible_key_3', + value: string | Immutable.List + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +; + +`; + +exports[`expression.js - flow-verify 4`] = ` +; + +; + + + {() => ( + + + + )} +; + + + {items.map(item => ( + + + + ))} +; + + + {function() { + return ( + + + + ); + }} +; + +; + + + test + +}/>; + + doLogClick("short", "short", data)} +/>; + + + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + } +/>; + + { + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + }} +/>; + +, + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +/>; + + + {data => doLogClick("short", "short", data)} +; + + + {data => + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + } +; + + + {data => { + doLogClick("long_name_long_name_long_name", "long_name_long_name_long_name", data) + }} +; + + + {( + key: "possible_key_1" | "possible_key_2" | "possible_key_3", + value: string | Immutable.List, + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; + +; + + + {() => ( + + + + )} +; + + + {items.map(item => ( + + + + ))} +; + + + {function() { + return ( + + + + ); + }} +; + +; + +test} />; + + doLogClick('short', 'short', data)} +/>; + + + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ) + } +/>; + + { + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ); + }} +/>; + + + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +/>; + + + {data => doLogClick('short', 'short', data)} +; + + + {data => + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ) + } +; + + + {data => { + doLogClick( + 'long_name_long_name_long_name', + 'long_name_long_name_long_name', + data + ); + }} +; + + + {( + key: 'possible_key_1' | 'possible_key_2' | 'possible_key_3', + value: string | Immutable.List + ) => { + this.setState({ + updatedTask: this.state.updatedTask.set(key, value) + }); + }} +; + +`; + exports[`flow_fix_me.js - flow-verify 1`] = ` const aDiv = ( /* $FlowFixMe */ @@ -689,6 +2711,51 @@ const aDiv = ( `; +exports[`flow_fix_me.js - flow-verify 2`] = ` +const aDiv = ( + /* $FlowFixMe */ +
+ Foo bar +
+); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const aDiv = ( + /* $FlowFixMe */ +
Foo bar
+); + +`; + +exports[`flow_fix_me.js - flow-verify 3`] = ` +const aDiv = ( + /* $FlowFixMe */ +
+ Foo bar +
+); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const aDiv = ( + /* $FlowFixMe */ +
Foo bar
+); + +`; + +exports[`flow_fix_me.js - flow-verify 4`] = ` +const aDiv = ( + /* $FlowFixMe */ +
+ Foo bar +
+); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const aDiv = ( + /* $FlowFixMe */ +
Foo bar
+); + +`; + exports[`html_escape.js - flow-verify 1`] = ` export default () => ; @@ -700,6 +2767,39 @@ export default () => ; `; +exports[`html_escape.js - flow-verify 2`] = ` +export default () => ; + +() => ; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +export default () => ; + +() => ; + +`; + +exports[`html_escape.js - flow-verify 3`] = ` +export default () => ; + +() => ; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +export default () => ; + +() => ; + +`; + +exports[`html_escape.js - flow-verify 4`] = ` +export default () => ; + +() => ; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +export default () => ; + +() => ; + +`; + exports[`hug.js - flow-verify 1`] = `
{__DEV__ @@ -773,6 +2873,225 @@ exports[`hug.js - flow-verify 1`] = ` `; +exports[`hug.js - flow-verify 2`] = ` +
+ {__DEV__ + ? this.renderDevApp() + :
+ {routes.map(route => ( + + ))} +
} +
; + +
+ {__DEV__ &&
+ {routes.map(route => ( + + ))} +
} +
; + +
+ {member.memberName.memberSomething + + (member.memberDef.memberSomething.signatures ? '()' : '')} +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
+ {__DEV__ ? ( + this.renderDevApp() + ) : ( +
+ {routes.map(route => ( + + ))} +
+ )} +
; + +
+ {__DEV__ && ( +
+ {routes.map(route => ( + + ))} +
+ )} +
; + +
+ {member.memberName.memberSomething + + (member.memberDef.memberSomething.signatures ? "()" : "")} +
; + +`; + +exports[`hug.js - flow-verify 3`] = ` +
+ {__DEV__ + ? this.renderDevApp() + :
+ {routes.map(route => ( + + ))} +
} +
; + +
+ {__DEV__ &&
+ {routes.map(route => ( + + ))} +
} +
; + +
+ {member.memberName.memberSomething + + (member.memberDef.memberSomething.signatures ? '()' : '')} +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
+ {__DEV__ ? ( + this.renderDevApp() + ) : ( +
+ {routes.map(route => ( + + ))} +
+ )} +
; + +
+ {__DEV__ && ( +
+ {routes.map(route => ( + + ))} +
+ )} +
; + +
+ {member.memberName.memberSomething + + (member.memberDef.memberSomething.signatures ? '()' : '')} +
; + +`; + +exports[`hug.js - flow-verify 4`] = ` +
+ {__DEV__ + ? this.renderDevApp() + :
+ {routes.map(route => ( + + ))} +
} +
; + +
+ {__DEV__ &&
+ {routes.map(route => ( + + ))} +
} +
; + +
+ {member.memberName.memberSomething + + (member.memberDef.memberSomething.signatures ? '()' : '')} +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
+ {__DEV__ ? ( + this.renderDevApp() + ) : ( +
+ {routes.map(route => ( + + ))} +
+ )} +
; + +
+ {__DEV__ && ( +
+ {routes.map(route => ( + + ))} +
+ )} +
; + +
+ {member.memberName.memberSomething + + (member.memberDef.memberSomething.signatures ? '()' : '')} +
; + +`; + exports[`logical-expression.js - flow-verify 1`] = `
{a || "b"} @@ -842,6 +3161,213 @@ exports[`logical-expression.js - flow-verify 1`] = ` `; +exports[`logical-expression.js - flow-verify 2`] = ` +
+ {a || "b"} +
; + +
+ {a && "b"} +
; + +
+ {a || } +
; + +
+ {a && } +
; + +
+ {a && make this text just so long enough to break this to the next line} +
; + +
+ {a && b && make this text just so long enough to break this to the next line} +
; + +
+ {a && +
+
+
+
} +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
{a || "b"}
; + +
{a && "b"}
; + +
{a || }
; + +
{a && }
; + +
+ {a && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && b && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && ( + +
+
+
+ + )} +
; + +`; + +exports[`logical-expression.js - flow-verify 3`] = ` +
+ {a || "b"} +
; + +
+ {a && "b"} +
; + +
+ {a || } +
; + +
+ {a && } +
; + +
+ {a && make this text just so long enough to break this to the next line} +
; + +
+ {a && b && make this text just so long enough to break this to the next line} +
; + +
+ {a && +
+
+
+
} +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
{a || 'b'}
; + +
{a && 'b'}
; + +
{a || }
; + +
{a && }
; + +
+ {a && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && b && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && ( + +
+
+
+ + )} +
; + +`; + +exports[`logical-expression.js - flow-verify 4`] = ` +
+ {a || "b"} +
; + +
+ {a && "b"} +
; + +
+ {a || } +
; + +
+ {a && } +
; + +
+ {a && make this text just so long enough to break this to the next line} +
; + +
+ {a && b && make this text just so long enough to break this to the next line} +
; + +
+ {a && +
+
+
+
} +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
{a || 'b'}
; + +
{a && 'b'}
; + +
{a || }
; + +
{a && }
; + +
+ {a && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && b && ( + + make this text just so long enough to break this to the next line + + )} +
; + +
+ {a && ( + +
+
+
+ + )} +
; + +`; + exports[`object-property.js - flow-verify 1`] = ` const tabs = [ { @@ -873,6 +3399,99 @@ const tabs = [ `; +exports[`object-property.js - flow-verify 2`] = ` +const tabs = [ + { + title: "General Info", + content: ( + + ) + } +]; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const tabs = [ + { + title: "General Info", + content: ( + + ) + } +]; + +`; + +exports[`object-property.js - flow-verify 3`] = ` +const tabs = [ + { + title: "General Info", + content: ( + + ) + } +]; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const tabs = [ + { + title: 'General Info', + content: ( + + ) + } +]; + +`; + +exports[`object-property.js - flow-verify 4`] = ` +const tabs = [ + { + title: "General Info", + content: ( + + ) + } +]; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const tabs = [ + { + title: 'General Info', + content: ( + + ) + } +]; + +`; + exports[`open-break.js - flow-verify 1`] = ` { @@ -908,6 +3527,111 @@ onClick={() => { `; +exports[`open-break.js - flow-verify 2`] = ` + { + a +}}>{header}{showSort}; + + { + a +}}>{header}; + +{\` a very long text that does not break \`}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + { + a; + }} +> + {header} + {showSort} +; + + { + a; + }} +> + {header} + +; + +{\` a very long text that does not break \`}; + +`; + +exports[`open-break.js - flow-verify 3`] = ` + { + a +}}>{header}{showSort}; + + { + a +}}>{header}; + +{\` a very long text that does not break \`}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + { + a; + }} +> + {header} + {showSort} +; + + { + a; + }} +> + {header} + +; + +{\` a very long text that does not break \`}; + +`; + +exports[`open-break.js - flow-verify 4`] = ` + { + a +}}>{header}{showSort}; + + { + a +}}>{header}; + +{\` a very long text that does not break \`}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + { + a; + }} +> + {header} + {showSort} +; + + { + a; + }} +> + {header} + +; + +{\` a very long text that does not break \`}; + +`; + exports[`parens.js - flow-verify 1`] = ` a = [ , + , +]; + +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a = [ + , + +]; + +
; + +`; + +exports[`parens.js - flow-verify 3`] = ` +a = [ + , + , +]; + +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a = [ + , + +]; + +
; + +`; + +exports[`parens.js - flow-verify 4`] = ` +a = [ + , + , +]; + +
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a = [ + , + +]; + +
; + +`; + exports[`quotes.js - flow-verify 1`] = `
;
;
"'} />; +
; +
; +
; +
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; -
; +
;
""} />; +
; +
; +
; +
; + +`; + +exports[`quotes.js - flow-verify 2`] = ` +
; +
; +
"'} />; +
; +
; +
; +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
; +
; +
""} />; +
; +
; +
; +
; + +`; + +exports[`quotes.js - flow-verify 3`] = ` +
; +
; +
"'} />; +
; +
; +
; +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
; +
; +
"'} />; +
; +
; +
; +
; + +`; + +exports[`quotes.js - flow-verify 4`] = ` +
; +
; +
"'} />; +
; +
; +
; +
; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
; +
; +
"'} />; +
; +
; +
; +
; `; @@ -1053,6 +4129,321 @@ class BreakingClass extends React.component { `; +exports[`return-statement.js - flow-verify 2`] = ` +const NonBreakingArrowExpression = () =>
; + +const BreakingArrowExpression = () =>
+
+ bla bla bla +
+
; + +const NonBreakingArrowExpressionWBody = () => { + return ( +
+ ); +}; + +const BreakingArrowExpressionWBody = () => { + return
+
+ bla bla bla +
+
+}; + +const NonBreakingFunction = function() { + return ( +
+ ); +}; + +const BreakingFunction = function() { + return
+
+ bla bla bla +
+
+}; + +class NonBreakingClass extends React.component { + render() { + return ( +
+ ); + } +} + +class BreakingClass extends React.component { + render() { + return
+
+ bla bla bla +
+
; + } +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const NonBreakingArrowExpression = () =>
; + +const BreakingArrowExpression = () => ( +
+
bla bla bla
+
+); + +const NonBreakingArrowExpressionWBody = () => { + return
; +}; + +const BreakingArrowExpressionWBody = () => { + return ( +
+
bla bla bla
+
+ ); +}; + +const NonBreakingFunction = function() { + return
; +}; + +const BreakingFunction = function() { + return ( +
+
bla bla bla
+
+ ); +}; + +class NonBreakingClass extends React.component { + render() { + return
; + } +} + +class BreakingClass extends React.component { + render() { + return ( +
+
bla bla bla
+
+ ); + } +} + +`; + +exports[`return-statement.js - flow-verify 3`] = ` +const NonBreakingArrowExpression = () =>
; + +const BreakingArrowExpression = () =>
+
+ bla bla bla +
+
; + +const NonBreakingArrowExpressionWBody = () => { + return ( +
+ ); +}; + +const BreakingArrowExpressionWBody = () => { + return
+
+ bla bla bla +
+
+}; + +const NonBreakingFunction = function() { + return ( +
+ ); +}; + +const BreakingFunction = function() { + return
+
+ bla bla bla +
+
+}; + +class NonBreakingClass extends React.component { + render() { + return ( +
+ ); + } +} + +class BreakingClass extends React.component { + render() { + return
+
+ bla bla bla +
+
; + } +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const NonBreakingArrowExpression = () =>
; + +const BreakingArrowExpression = () => ( +
+
bla bla bla
+
+); + +const NonBreakingArrowExpressionWBody = () => { + return
; +}; + +const BreakingArrowExpressionWBody = () => { + return ( +
+
bla bla bla
+
+ ); +}; + +const NonBreakingFunction = function() { + return
; +}; + +const BreakingFunction = function() { + return ( +
+
bla bla bla
+
+ ); +}; + +class NonBreakingClass extends React.component { + render() { + return
; + } +} + +class BreakingClass extends React.component { + render() { + return ( +
+
bla bla bla
+
+ ); + } +} + +`; + +exports[`return-statement.js - flow-verify 4`] = ` +const NonBreakingArrowExpression = () =>
; + +const BreakingArrowExpression = () =>
+
+ bla bla bla +
+
; + +const NonBreakingArrowExpressionWBody = () => { + return ( +
+ ); +}; + +const BreakingArrowExpressionWBody = () => { + return
+
+ bla bla bla +
+
+}; + +const NonBreakingFunction = function() { + return ( +
+ ); +}; + +const BreakingFunction = function() { + return
+
+ bla bla bla +
+
+}; + +class NonBreakingClass extends React.component { + render() { + return ( +
+ ); + } +} + +class BreakingClass extends React.component { + render() { + return
+
+ bla bla bla +
+
; + } +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const NonBreakingArrowExpression = () =>
; + +const BreakingArrowExpression = () => ( +
+
bla bla bla
+
+); + +const NonBreakingArrowExpressionWBody = () => { + return
; +}; + +const BreakingArrowExpressionWBody = () => { + return ( +
+
bla bla bla
+
+ ); +}; + +const NonBreakingFunction = function() { + return
; +}; + +const BreakingFunction = function() { + return ( +
+
bla bla bla
+
+ ); +}; + +class NonBreakingClass extends React.component { + render() { + return
; + } +} + +class BreakingClass extends React.component { + render() { + return ( +
+
bla bla bla
+
+ ); + } +} + +`; + exports[`spacing.js - flow-verify 1`] = ` const Labels = { label1: ( @@ -1083,3 +4474,96 @@ const Labels = { }; `; + +exports[`spacing.js - flow-verify 2`] = ` +const Labels = { + label1: ( + + Label 1 + + ), + + label2: ( + + Label 2 + + ), + + label3: ( + + Label 3 + + ), +}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const Labels = { + label1: Label 1, + + label2: Label 2, + + label3: Label 3 +}; + +`; + +exports[`spacing.js - flow-verify 3`] = ` +const Labels = { + label1: ( + + Label 1 + + ), + + label2: ( + + Label 2 + + ), + + label3: ( + + Label 3 + + ), +}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const Labels = { + label1: Label 1, + + label2: Label 2, + + label3: Label 3 +}; + +`; + +exports[`spacing.js - flow-verify 4`] = ` +const Labels = { + label1: ( + + Label 1 + + ), + + label2: ( + + Label 2 + + ), + + label3: ( + + Label 3 + + ), +}; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +const Labels = { + label1: Label 1, + + label2: Label 2, + + label3: Label 3 +}; + +`; diff --git a/tests/jsx/jsfmt.spec.js b/tests/jsx/jsfmt.spec.js index aeb016da..687ad179 100644 --- a/tests/jsx/jsfmt.spec.js +++ b/tests/jsx/jsfmt.spec.js @@ -1 +1,16 @@ -run_spec(__dirname, ["flow", "babylon", "typescript"]); +run_spec(__dirname, ["flow", "babylon", "typescript"], { + singleQuote: false, + jsxSingleQuote: false +}); +run_spec(__dirname, ["flow", "babylon", "typescript"], { + singleQuote: false, + jsxSingleQuote: true +}); +run_spec(__dirname, ["flow", "babylon", "typescript"], { + singleQuote: true, + jsxSingleQuote: false +}); +run_spec(__dirname, ["flow", "babylon", "typescript"], { + singleQuote: true, + jsxSingleQuote: true +}); diff --git a/tests/jsx/quotes.js b/tests/jsx/quotes.js index 304e72c9..6982466f 100644 --- a/tests/jsx/quotes.js +++ b/tests/jsx/quotes.js @@ -1,3 +1,36 @@
;
;
"'} />; +
; +
; +
; +
; diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index 4e2e3af4..572f147a 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -65,6 +65,8 @@ Format options: Defaults to css. --jsx-bracket-same-line Put > on the last line instead of at a new line. Defaults to false. + --jsx-single-quote Use single quotes in JSX. + Defaults to false. --parser Which parser to use. --print-width The line length where Prettier will try wrap. @@ -206,6 +208,8 @@ Format options: Defaults to css. --jsx-bracket-same-line Put > on the last line instead of at a new line. Defaults to false. + --jsx-single-quote Use single quotes in JSX. + Defaults to false. --parser Which parser to use. --print-width The line length where Prettier will try wrap. diff --git a/tests_integration/__tests__/__snapshots__/help-options.js.snap b/tests_integration/__tests__/__snapshots__/help-options.js.snap index 8f7ac365..e45689f1 100644 --- a/tests_integration/__tests__/__snapshots__/help-options.js.snap +++ b/tests_integration/__tests__/__snapshots__/help-options.js.snap @@ -196,6 +196,19 @@ Default: false exports[`show detailed usage with --help jsx-bracket-same-line (write) 1`] = `Array []`; +exports[`show detailed usage with --help jsx-single-quote (stderr) 1`] = `""`; + +exports[`show detailed usage with --help jsx-single-quote (stdout) 1`] = ` +"--jsx-single-quote + + Use single quotes in JSX. + +Default: false +" +`; + +exports[`show detailed usage with --help jsx-single-quote (write) 1`] = `Array []`; + exports[`show detailed usage with --help list-different (stderr) 1`] = `""`; exports[`show detailed usage with --help list-different (stdout) 1`] = ` diff --git a/tests_integration/__tests__/__snapshots__/schema.js.snap b/tests_integration/__tests__/__snapshots__/schema.js.snap index 33b0b7aa..b2afcf6a 100644 --- a/tests_integration/__tests__/__snapshots__/schema.js.snap +++ b/tests_integration/__tests__/__snapshots__/schema.js.snap @@ -82,6 +82,11 @@ This option cannot be used with --range-start and --range-end.", "description": "Put > on the last line instead of at a new line.", "type": "boolean", }, + "jsxSingleQuote": Object { + "default": false, + "description": "Use single quotes in JSX.", + "type": "boolean", + }, "parser": Object { "default": undefined, "description": "Which parser to use.", diff --git a/tests_integration/__tests__/__snapshots__/support-info.js.snap b/tests_integration/__tests__/__snapshots__/support-info.js.snap index 30c6bfc0..125e06cc 100644 --- a/tests_integration/__tests__/__snapshots__/support-info.js.snap +++ b/tests_integration/__tests__/__snapshots__/support-info.js.snap @@ -489,7 +489,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` \\"type\\": \\"boolean\\", }, \\"cursorOffset\\": Object { -@@ -56,10 +85,19 @@ +@@ -56,33 +85,61 @@ }, \\"filepath\\": Object { \\"default\\": undefined, @@ -509,7 +509,17 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` \\"type\\": \\"boolean\\", }, \\"jsxBracketSameLine\\": Object { -@@ -73,16 +111,31 @@ + \\"default\\": false, + \\"type\\": \\"boolean\\", + }, ++ \\"jsxSingleQuote\\": Object { ++ \\"default\\": false, ++ \\"type\\": \\"boolean\\", ++ }, + \\"parser\\": Object { + \\"choices\\": Array [ + \\"flow\\", + \\"babylon\\", \\"typescript\\", \\"css\\", \\"less\\", @@ -542,7 +552,7 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = ` \\"range\\": Object { \\"end\\": Infinity, \\"start\\": 0, -@@ -90,14 +143,15 @@ +@@ -90,14 +147,15 @@ }, \\"type\\": \\"int\\", }, @@ -1019,6 +1029,15 @@ exports[`CLI --support-info (stdout) 1`] = ` \\"since\\": \\"0.17.0\\", \\"type\\": \\"boolean\\" }, + { + \\"category\\": \\"JavaScript\\", + \\"default\\": false, + \\"description\\": \\"Use single quotes in JSX.\\", + \\"name\\": \\"jsxSingleQuote\\", + \\"pluginDefaults\\": {}, + \\"since\\": \\"1.15.0\\", + \\"type\\": \\"boolean\\" + }, { \\"category\\": \\"Global\\", \\"choices\\": [