Skip to content

Commit

Permalink
Fix TSX output for components with newlines in the starting tag (#1017)
Browse files Browse the repository at this point in the history
* fix(tsx): Add leading space when there's a newline in a starting tag

* chore: changeset

* nit: better comments

* nit: another comment fix

* nit: appease biome
  • Loading branch information
Princesseuh authored Jul 9, 2024
1 parent 6b7c12f commit 8803da6
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-spoons-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/compiler': patch
---

Fixes newlines in opening tag generating buggy code in TSX
11 changes: 7 additions & 4 deletions internal/printer/print-to-tsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,23 @@ func isValidTSXAttribute(a Attribute) bool {
if i == 0 && !isValidFirstRune(ch) {
return false
}
// See https://mathiasbynens.be/notes/javascript-identifiers

// See https://tc39.es/ecma262/#prod-IdentifierName
if i != 0 && !(isValidFirstRune(ch) ||
unicode.In(ch, unicode.Mn, unicode.Mc, unicode.Nd, unicode.Pc)) &&
// : is allowed inside TSX attributes, for namespaces purpose
// See https://facebook.github.io/jsx/#prod-JSXNamespacedName
ch != ':' {
// - is allowed inside TSX attributes, for custom attributes
// See https://facebook.github.io/jsx/#prod-JSXIdentifier
ch != ':' && ch != '-' {
return false
}
}

return true
}

// See https://mathiasbynens.be/notes/javascript-identifiers
// See https://tc39.es/ecma262/#prod-IdentifierStartChar
func isValidFirstRune(r rune) bool {
return r == '$' || r == '_' || unicode.In(r,
unicode.Lu,
Expand Down Expand Up @@ -489,7 +492,7 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s, typeof %s`, propsI
p.addSourceMapping(loc.Loc{Start: endLoc})
endLoc++
break
} else if unicode.IsSpace(rune(c)) {
} else if unicode.IsSpace(rune(c)) || (c == '\\' && p.sourcetext[endLoc+1:][0] == 'n') {
hasLeadingSpace = true
leadingSpaceLoc = endLoc
endLoc++
Expand Down
15 changes: 13 additions & 2 deletions packages/compiler/test/tsx/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ export default function __AstroComponent_(_props: Record<string, any>): any {}\n
});

test("Don't move attributes to spread unnecessarily", async () => {
const input = `<div 丽dfds_fsfdsfs name="value"></div>`;
const input = `<div 丽dfds_fsfdsfs aria-blarg name="value"></div>`;
const output = `${TSXPrefix}<Fragment>
<div 丽dfds_fsfdsfs name="value"></div>
<div 丽dfds_fsfdsfs aria-blarg name="value"></div>
</Fragment>
export default function __AstroComponent_(_props: Record<string, any>): any {}\n`;
const { code } = await convertToTSX(input, { sourcemap: 'external' });
Expand Down Expand Up @@ -245,6 +245,17 @@ export default function __AstroComponent_(_props: Record<string, any>): any {}\n
assert.snapshot(code, output, 'expected code to match snapshot');
});

test('preserves line returns in tag by transforming to space', async () => {
const input = `<Button
>`;
const output = `${TSXPrefix}<Fragment>
<Button ></Button>
</Fragment>
export default function __AstroComponent_(_props: Record<string, any>): any {}\n`;
const { code } = await convertToTSX(input, { sourcemap: 'external' });
assert.snapshot(code, output, 'expected code to match snapshot');
});

test('return ranges', async () => {
const input = `---\nconsole.log("Hello!")\n---\n\n<div></div>`;
const { metaRanges } = await convertToTSX(input, { sourcemap: 'external' });
Expand Down

0 comments on commit 8803da6

Please sign in to comment.