Weird formatting issue with prependWhitespace() for a JsxAttribute
Describe the bug
Version: 9.1.0
Hey @dsherret. I'm getting a weird formatting issue when trying to add some whitespace before a JsxAttribute node.
I'm trying to get a new attribute to be on its own line. So I have this (minimal example) tag:
<div
className="my-class"
>
Text
</div>
Adding a new attribute (align="center") with the .addAttribute() API results in the following: (attribute on same line)
<div
className="my-class" align="center"
>
Text
</div>
So I'm trying to prepend a line break and 4 spaces before the new 'align' attribute node (newAttr.prependWhitespace('\n ')), but the formatting ends up like this:
<div
className="my-class"
align="center" <-- oops, 8 spaces somehow
>
Text
</div>
If I prepend just a single line break (\n) without any spaces, I get this:
<div
className="my-class"
align="center" <-- line break with no spaces
>
Text
</div>
And if I prepend a line break and just a single space ('\n '):
<div
className="my-class"
align="center" <-- oops, 5 spaces somehow
>
Text
</div>
I think the formatter is trying to align the new attribute vertically with the previous attribute, but then adding spaces after that.
To Reproduce
import { JsxOpeningElement, Project, SyntaxKind, ts } from 'ts-morph';
console.log(ts.version); // 4.1.2
const project = new Project();
const sourceFile = project.createSourceFile('tmp.tsx', `
const MyComponent = () => {
return (
<div
className="my-class"
>
Text
</div>
);
};
`);
const jsxEl = sourceFile.getFirstDescendantByKindOrThrow(SyntaxKind.JsxOpeningElement) as JsxOpeningElement;
const newAttr = jsxEl.addAttribute({ name: 'align', initializer: '"center"' });
newAttr.prependWhitespace('\n '); // somehow inserts 16 spaces in this case
console.log(sourceFile.getFullText());
Output from this particular example:
const MyComponent = () => {
return (
<div
className="my-class"
align="center" // <-- 16 spaces
>
Text
</div>
);
};
Expected behavior
I would have expected the line break and the exact 4 spaces I put in to be present after I call prependWhitespace('\n ').
However, if there's some formatting that's supposed to go on here, it seems that maybe it should trigger from just adding a \n char?
Hmmm... that should be fixed. That said, you should check out dprint 😅
Very cool project @dsherret! And written in Rust too, how fun :)
Unfortunately in this case I can't run a formatter though. The tool we're writing is a codemod tool for users of our React library, and I don't want to reformat the full source file if we're just making a small edit to say, a single JSX element. Running a formatter could create a lot of noise in the diffs, and we may also accidentally reformat it in conflict with their project's standards.
Do you think fixing this is a quick thing or kind of involved? If you can direct me to the source files I might need to touch, I could submit a PR 👍
Best, Greg