Improve JSX output when there is a single expression (#2274)
parent
95a5f11be9
commit
be600337eb
|
@ -3739,7 +3739,7 @@ function printJSXChildren(path, options, print, jsxWhitespace) {
|
||||||
children.push(jsxWhitespace);
|
children.push(jsxWhitespace);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Ideally this would be a `softline` to allow a break between
|
// Ideally this would be a `hardline` to allow a break between
|
||||||
// tags and text.
|
// tags and text.
|
||||||
// Unfortunately Facebook have a custom translation pipeline
|
// Unfortunately Facebook have a custom translation pipeline
|
||||||
// (https://github.com/prettier/prettier/issues/1581#issuecomment-300975032)
|
// (https://github.com/prettier/prettier/issues/1581#issuecomment-300975032)
|
||||||
|
@ -3762,23 +3762,14 @@ function printJSXChildren(path, options, print, jsxWhitespace) {
|
||||||
children.push(jsxWhitespace);
|
children.push(jsxWhitespace);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Convert `{" "}` to jsxWhitespace so it can be printed as a standard
|
|
||||||
// space if needed.
|
|
||||||
if (isJSXWhitespaceExpression(child)) {
|
|
||||||
children.push("");
|
|
||||||
children.push(jsxWhitespace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const printedChild = print(childPath);
|
const printedChild = print(childPath);
|
||||||
children.push(printedChild);
|
children.push(printedChild);
|
||||||
|
|
||||||
const next = n.children[i + 1];
|
const next = n.children[i + 1];
|
||||||
const directlyFollowedByMeaningfulText =
|
const directlyFollowedByMeaningfulText =
|
||||||
next && isMeaningfulJSXText(next) && !/^[ \n\r\t]/.test(rawText(next));
|
next && isMeaningfulJSXText(next) && !/^[ \n\r\t]/.test(rawText(next));
|
||||||
const followedByJSXWhitespace = next && isJSXWhitespaceExpression(next);
|
if (directlyFollowedByMeaningfulText) {
|
||||||
if (directlyFollowedByMeaningfulText || followedByJSXWhitespace) {
|
// Potentially this could be a hardline as well.
|
||||||
// Potentially this could be a softline as well.
|
|
||||||
// See the comment above about the Facebook translation pipeline as
|
// See the comment above about the Facebook translation pipeline as
|
||||||
// to why this is an empty string.
|
// to why this is an empty string.
|
||||||
children.push("");
|
children.push("");
|
||||||
|
@ -3837,11 +3828,30 @@ function printJSXElement(path, options, print) {
|
||||||
return openingLines;
|
return openingLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert `{" "}` to text nodes containing a space.
|
||||||
|
// This makes it easy to turn them into `jsxWhitespace` which
|
||||||
|
// can then print as either a space or `{" "}` when breaking.
|
||||||
|
n.children = n.children.map(child => {
|
||||||
|
if (isJSXWhitespaceExpression(child)) {
|
||||||
|
return {
|
||||||
|
type: "JSXText",
|
||||||
|
value: " ",
|
||||||
|
raw: " "
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return child;
|
||||||
|
});
|
||||||
|
|
||||||
|
const parent = path.getParentNode();
|
||||||
|
const parentContainsText =
|
||||||
|
parent.type === "JSXElement" &&
|
||||||
|
parent.children.filter(child => isMeaningfulJSXText(child)).length > 0;
|
||||||
|
|
||||||
const containsTag =
|
const containsTag =
|
||||||
n.children.filter(child => child.type === "JSXElement").length > 0;
|
n.children.filter(child => child.type === "JSXElement").length > 0;
|
||||||
const containsMultipleExpressions =
|
const numExpressions = n.children.filter(
|
||||||
n.children.filter(child => child.type === "JSXExpressionContainer").length >
|
child => child.type === "JSXExpressionContainer"
|
||||||
1;
|
).length;
|
||||||
const containsMultipleAttributes = n.openingElement.attributes.length > 1;
|
const containsMultipleAttributes = n.openingElement.attributes.length > 1;
|
||||||
|
|
||||||
// Record any breaks. Should never go from true to false, only false to true.
|
// Record any breaks. Should never go from true to false, only false to true.
|
||||||
|
@ -3849,7 +3859,7 @@ function printJSXElement(path, options, print) {
|
||||||
willBreak(openingLines) ||
|
willBreak(openingLines) ||
|
||||||
containsTag ||
|
containsTag ||
|
||||||
containsMultipleAttributes ||
|
containsMultipleAttributes ||
|
||||||
containsMultipleExpressions;
|
(parentContainsText ? numExpressions > 1 : numExpressions > 0);
|
||||||
|
|
||||||
const rawJsxWhitespace = options.singleQuote ? "{' '}" : '{" "}';
|
const rawJsxWhitespace = options.singleQuote ? "{' '}" : '{" "}';
|
||||||
const jsxWhitespace = ifBreak(concat([rawJsxWhitespace, softline]), " ");
|
const jsxWhitespace = ifBreak(concat([rawJsxWhitespace, softline]), " ");
|
||||||
|
|
|
@ -304,7 +304,10 @@ export const bem = block =>
|
||||||
<FlatList
|
<FlatList
|
||||||
renderItem={(
|
renderItem={(
|
||||||
info // $FlowExpectedError - bad widgetCount type 6, should be Object
|
info // $FlowExpectedError - bad widgetCount type 6, should be Object
|
||||||
) => <span>{info.item.widget.missingProp}</span>}
|
) =>
|
||||||
|
<span>
|
||||||
|
{info.item.widget.missingProp}
|
||||||
|
</span>}
|
||||||
data={data}
|
data={data}
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
|
|
|
@ -497,7 +497,9 @@ Observable.of(process)
|
||||||
.takeUntil(exit);
|
.takeUntil(exit);
|
||||||
|
|
||||||
// Comments disappear inside of JSX
|
// Comments disappear inside of JSX
|
||||||
<div>{/* Some comment */}</div>;
|
<div>
|
||||||
|
{/* Some comment */}
|
||||||
|
</div>;
|
||||||
|
|
||||||
// Comments in JSX tag are placed in a non optimal way
|
// Comments in JSX tag are placed in a non optimal way
|
||||||
<div
|
<div
|
||||||
|
@ -596,15 +598,23 @@ exports[`jsx.js 1`] = `
|
||||||
|
|
||||||
<div>{/*<div> Some very v ery very very long line to break line width limit </div>*/}</div>;
|
<div>{/*<div> Some very v ery very very long line to break line width limit </div>*/}</div>;
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
<div>{/* comment */}</div>;
|
<div>
|
||||||
|
{/* comment */}
|
||||||
|
</div>;
|
||||||
|
|
||||||
<div>{/* comment */}</div>;
|
<div>
|
||||||
|
{/* comment */}
|
||||||
|
</div>;
|
||||||
|
|
||||||
<div>{/* comment
|
<div>
|
||||||
*/}</div>;
|
{/* comment
|
||||||
|
*/}
|
||||||
|
</div>;
|
||||||
|
|
||||||
<div>{a /* comment
|
<div>
|
||||||
*/}</div>;
|
{a /* comment
|
||||||
|
*/}
|
||||||
|
</div>;
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
@ -614,9 +624,13 @@ exports[`jsx.js 1`] = `
|
||||||
}
|
}
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
<div>{/* comment */}</div>;
|
<div>
|
||||||
|
{/* comment */}
|
||||||
|
</div>;
|
||||||
|
|
||||||
<div>{/* comment */}</div>;
|
<div>
|
||||||
|
{/* comment */}
|
||||||
|
</div>;
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
|
|
@ -222,8 +222,12 @@ declare function ExpectsProps(props: { name: string }, children: any): string;
|
||||||
declare function ExpectsChildrenTuple(props: any, children: [string]): string;
|
declare function ExpectsChildrenTuple(props: any, children: [string]): string;
|
||||||
<ExpectsChildrenTuple />; // Error - mising child
|
<ExpectsChildrenTuple />; // Error - mising child
|
||||||
<ExpectsChildrenTuple>Hi</ExpectsChildrenTuple>; // No error
|
<ExpectsChildrenTuple>Hi</ExpectsChildrenTuple>; // No error
|
||||||
<ExpectsChildrenTuple>{123}</ExpectsChildrenTuple>; // Error: number ~> string
|
<ExpectsChildrenTuple>
|
||||||
<ExpectsChildrenTuple>Hi {"there"}</ExpectsChildrenTuple>; // Error: too many children
|
{123}
|
||||||
|
</ExpectsChildrenTuple>; // Error: number ~> string
|
||||||
|
<ExpectsChildrenTuple>
|
||||||
|
Hi {"there"}
|
||||||
|
</ExpectsChildrenTuple>; // Error: too many children
|
||||||
|
|
||||||
declare function ExpectsChildrenArray(
|
declare function ExpectsChildrenArray(
|
||||||
props: any,
|
props: any,
|
||||||
|
@ -231,8 +235,12 @@ declare function ExpectsChildrenArray(
|
||||||
): string;
|
): string;
|
||||||
<ExpectsChildrenArray />; // No error - 0 children is fine
|
<ExpectsChildrenArray />; // No error - 0 children is fine
|
||||||
<ExpectsChildrenArray>Hi</ExpectsChildrenArray>; // No error - 1 child is fine
|
<ExpectsChildrenArray>Hi</ExpectsChildrenArray>; // No error - 1 child is fine
|
||||||
<ExpectsChildrenArray>{123}</ExpectsChildrenArray>; // Error: number ~> string
|
<ExpectsChildrenArray>
|
||||||
<ExpectsChildrenArray>Hi {"there"}</ExpectsChildrenArray>; // No error - 2 children is fine
|
{123}
|
||||||
|
</ExpectsChildrenArray>; // Error: number ~> string
|
||||||
|
<ExpectsChildrenArray>
|
||||||
|
Hi {"there"}
|
||||||
|
</ExpectsChildrenArray>; // No error - 2 children is fine
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -793,7 +793,11 @@ class Example extends React.Component {
|
||||||
props: { bar: string };
|
props: { bar: string };
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div>{this.props.bar}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.bar}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +869,11 @@ var ReactClass = React.createClass({
|
||||||
render: function(): any {
|
render: function(): any {
|
||||||
// Any state access here seems to make state any
|
// Any state access here seems to make state any
|
||||||
this.state;
|
this.state;
|
||||||
return <div>{this.state.bar.qux}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.state.bar.qux}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -973,7 +981,11 @@ var C = React.createClass({
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.setState({ y: 0 });
|
this.setState({ y: 0 });
|
||||||
return <div>{this.state.z}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.state.z}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -741,7 +741,11 @@ class Bar extends React.Component {
|
||||||
test: number
|
test: number
|
||||||
};
|
};
|
||||||
render() {
|
render() {
|
||||||
return <div>{this.props.test}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.test}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,9 +1623,17 @@ var Example = React.createClass({
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
if (typeof this.props.prop === "string") {
|
if (typeof this.props.prop === "string") {
|
||||||
return <div>{this.props.prop}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.prop}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return <div>{this.props.prop.toFixed(2)}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.prop.toFixed(2)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -38,7 +38,11 @@ var HelloLocal = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function(): React.Element<*> {
|
render: function(): React.Element<*> {
|
||||||
return <div>{this.props.name}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -82,7 +86,11 @@ var Hello = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function(): React.Element<*> {
|
render: function(): React.Element<*> {
|
||||||
return <div>{this.props.name}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -128,7 +136,11 @@ class HelloLocal extends React.Component<void, { name: string }, void> {
|
||||||
name: React.PropTypes.string.isRequired
|
name: React.PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
render(): React.Element<*> {
|
render(): React.Element<*> {
|
||||||
return <div>{this.props.name}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +186,11 @@ class Hello extends React.Component<void, { name: string }, void> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Element<*> {
|
render(): React.Element<*> {
|
||||||
return <div>{this.props.name}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +236,11 @@ class HelloLocal extends React.Component<void, Props, void> {
|
||||||
props: Props;
|
props: Props;
|
||||||
|
|
||||||
render(): React.Element<*> {
|
render(): React.Element<*> {
|
||||||
return <div>{this.props.name}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +286,11 @@ class Hello extends React.Component<{}, Props, void> {
|
||||||
static defaultProps: {};
|
static defaultProps: {};
|
||||||
|
|
||||||
render(): React.Element<*> {
|
render(): React.Element<*> {
|
||||||
return <div>{this.props.name}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.name}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,9 +160,14 @@ const render7B = () =>
|
||||||
</span>
|
</span>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
const render8 = props => <div>{props.text}</div>;
|
const render8 = props =>
|
||||||
|
<div>
|
||||||
|
{props.text}
|
||||||
|
</div>;
|
||||||
const render9 = props =>
|
const render9 = props =>
|
||||||
<div>{props.looooooooooooooooooooooooooooooong_text}</div>;
|
<div>
|
||||||
|
{props.looooooooooooooooooooooooooooooong_text}
|
||||||
|
</div>;
|
||||||
const render10 = props =>
|
const render10 = props =>
|
||||||
<div>
|
<div>
|
||||||
{props.even_looooooooooooooooooooooooooooooooooooooooooonger_contents}
|
{props.even_looooooooooooooooooooooooooooooooooooooooooonger_contents}
|
||||||
|
|
|
@ -284,7 +284,9 @@ const els = items.map(item => (
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
const els = items.map(item =>
|
const els = items.map(item =>
|
||||||
<div className="whatever">
|
<div className="whatever">
|
||||||
<span>{children}</span>
|
<span>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,15 @@ const MyCoolList = ({ things }) =>
|
||||||
|
|
||||||
const MyCoolThing = ({ thingo }) => <li>{thingo}</li>;
|
const MyCoolThing = ({ thingo }) => <li>{thingo}</li>;
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
const MyCoolList = ({ things }) => <ul>{things.map(MyCoolThing)}</ul>;
|
const MyCoolList = ({ things }) =>
|
||||||
|
<ul>
|
||||||
|
{things.map(MyCoolThing)}
|
||||||
|
</ul>;
|
||||||
|
|
||||||
const MyCoolThing = ({ thingo }) => <li>{thingo}</li>;
|
const MyCoolThing = ({ thingo }) =>
|
||||||
|
<li>
|
||||||
|
{thingo}
|
||||||
|
</li>;
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue